Esempio n. 1
0
        private List <Obstacle> FinalizeProcessing(List <Obstacle> trackedObstacles, List <Obstacle> untrackedObstacles, CarTimestamp timestamp)
        {
            List <Obstacle> finalObstacles = new List <Obstacle>(trackedObstacles.Count + untrackedObstacles.Count);

            finalObstacles.AddRange(trackedObstacles);
            finalObstacles.AddRange(untrackedObstacles);

            Obstacle leftObstacle  = GetSideObstacle(currentLeftSideObstacles);
            Obstacle rightObstacle = GetSideObstacle(currentRightSideObstacles);

            int extraCount = 0;

            if (leftObstacle != null)
            {
                extraCount++;
            }
            if (rightObstacle != null)
            {
                extraCount++;
            }

            List <int> ignoredObstacles = this.lastIgnoredObstacles;

            OperationalObstacle[] uiObstacles = new OperationalObstacle[finalObstacles.Count + extraCount];

            int i;

            for (i = 0; i < finalObstacles.Count; i++)
            {
                Obstacle obs = finalObstacles[i];

                obs.minSpacing = min_spacing[(int)obs.obstacleClass] + ExtraSpacing;
                obs.desSpacing = des_spacing[(int)obs.obstacleClass] + ExtraSpacing;

                try {
                    obs.cspacePolygon = Polygon.ConvexMinkowskiConvolution(conv_polygon[(int)obs.obstacleClass], obs.AvoidancePolygon);
                }
                catch (Exception) {
                    OperationalTrace.WriteWarning("error computing minkowski convolution in finalize processing");
                    try {
                        obs.cspacePolygon = obs.AvoidancePolygon.Inflate(TahoeParams.T / 2.0 + min_spacing[(int)obs.obstacleClass]);
                    }
                    catch (Exception) {
                        obs.cspacePolygon = obs.AvoidancePolygon;
                    }
                }

                OperationalObstacle uiObs = new OperationalObstacle();
                uiObs.age           = obs.age;
                uiObs.obstacleClass = obs.obstacleClass;
                uiObs.poly          = obs.AvoidancePolygon;

                uiObs.headingValid = obs.absoluteHeadingValid;
                uiObs.heading      = obs.absoluteHeading;

                if (ignoredObstacles != null)
                {
                    uiObs.ignored = ignoredObstacles.Contains(obs.trackID);
                }

                uiObstacles[i] = uiObs;
            }

            if (leftObstacle != null)
            {
                OperationalObstacle uiObs = new OperationalObstacle();
                uiObs.age           = leftObstacle.age;
                uiObs.obstacleClass = leftObstacle.obstacleClass;
                uiObs.poly          = leftObstacle.AvoidancePolygon;
                uiObstacles[i++]    = uiObs;
            }

            if (rightObstacle != null)
            {
                OperationalObstacle uiObs = new OperationalObstacle();
                uiObs.age           = rightObstacle.age;
                uiObs.obstacleClass = rightObstacle.obstacleClass;
                uiObs.poly          = rightObstacle.AvoidancePolygon;
                uiObstacles[i++]    = uiObs;
            }

            Services.UIService.PushObstacles(uiObstacles, timestamp, "obstacles", true);

            return(finalObstacles);
        }
Esempio n. 2
0
        private List <Obstacle> ProcessTrackedClusters(SceneEstimatorTrackedClusterCollection clusters, Rect vehicleBox)
        {
            List <Obstacle> obstacles = new List <Obstacle>(clusters.clusters.Length);

            // get the list of previous id's
            SortedList <int, Obstacle> previousID;

            if (processedObstacles != null)
            {
                previousID = new SortedList <int, Obstacle>(processedObstacles.obstacles.Count);
                foreach (Obstacle obs in processedObstacles.obstacles)
                {
                    if (obs != null && obs.trackID != -1 && !previousID.ContainsKey(obs.trackID))
                    {
                        previousID.Add(obs.trackID, obs);
                    }
                }
            }
            else
            {
                previousID = new SortedList <int, Obstacle>();
            }

            List <Coordinates> goodPoints = new List <Coordinates>(1500);

            Circle  mergeCircle  = new Circle(merge_expansion_size, Coordinates.Zero);
            Polygon mergePolygon = mergeCircle.ToPolygon(24);

            foreach (SceneEstimatorTrackedCluster cluster in clusters.clusters)
            {
                // ignore deleted targets
                if (cluster.statusFlag == SceneEstimatorTargetStatusFlag.TARGET_STATE_DELETED || cluster.statusFlag == SceneEstimatorTargetStatusFlag.TARGET_STATE_OCCLUDED_FULL || cluster.relativePoints == null || cluster.relativePoints.Length < 3)
                {
                    continue;
                }

                Obstacle obs = new Obstacle();

                obs.trackID    = cluster.id;
                obs.speed      = cluster.speed;
                obs.speedValid = cluster.speedValid;
                obs.occuluded  = cluster.statusFlag != SceneEstimatorTargetStatusFlag.TARGET_STATE_ACTIVE;

                // update the age
                Obstacle prevTrack = null;
                previousID.TryGetValue(cluster.id, out prevTrack);

                goodPoints.Clear();

                int numOccupancyDeleted = 0;
                foreach (Coordinates pt in cluster.relativePoints)
                {
                    if (!vehicleBox.IsInside(pt))
                    {
                        if (useOccupancyGrid && Services.OccupancyGrid.GetOccupancy(pt) == OccupancyStatus.Free)
                        {
                            occupancyDeletedCount++;
                            numOccupancyDeleted++;
                        }
                        else
                        {
                            goodPoints.Add(pt);
                        }
                    }
                }

                if (goodPoints.Count < 3)
                {
                    continue;
                }

                IList <Polygon> polys;
                if (obs.occuluded && numOccupancyDeleted > 0)
                {
                    polys = WrapAndSplit(goodPoints, 1, 2.5);
                }
                else
                {
                    polys = new Polygon[] { Polygon.GrahamScan(goodPoints) };
                }

                obs.absoluteHeadingValid = cluster.headingValid;
                obs.absoluteHeading      = cluster.absoluteHeading;

                // set the obstacle polygon for calculate obstacle distance
                Polygon obsPoly        = Polygon.GrahamScan(goodPoints);
                double  targetDistance = GetObstacleDistance(obsPoly);

                ObstacleClass impliedClass = ObstacleClass.DynamicUnknown;
                switch (cluster.targetClass)
                {
                case SceneEstimatorTargetClass.TARGET_CLASS_CARLIKE:
                    if (cluster.isStopped)
                    {
                        impliedClass = ObstacleClass.DynamicStopped;
                    }
                    else
                    {
                        impliedClass = ObstacleClass.DynamicCarlike;
                    }
                    break;

                case SceneEstimatorTargetClass.TARGET_CLASS_NOTCARLIKE:
                    impliedClass = ObstacleClass.DynamicNotCarlike;
                    break;

                case SceneEstimatorTargetClass.TARGET_CLASS_UNKNOWN:
                    impliedClass = ObstacleClass.DynamicUnknown;
                    break;
                }

                if (prevTrack == null)
                {
                    obs.age = 1;
                    // we haven't seen this track before, determine what the implied class is
                    if (targetDistance < target_class_ignore_dist)
                    {
                        impliedClass = ObstacleClass.DynamicUnknown;
                    }
                }
                else
                {
                    obs.age = prevTrack.age + 1;
                    // if we've seen this target before and we've labelled it as unknown and it is labelled as car-like now, check the distance
                    if (prevTrack.obstacleClass == ObstacleClass.DynamicUnknown && targetDistance < target_class_ignore_dist && obs.age < target_class_ignore_age)
                    {
                        impliedClass = ObstacleClass.DynamicUnknown;
                    }
                }

                // get the off-road percentage
                double offRoadPercent = GetPercentOffRoad(obs.obstaclePolygon);

                if (offRoadPercent > 0.65)
                {
                    obs.offroadAge = obs.age;
                }

                // now check if we're labelling the obstacle as car-like if it has been off-road in the last second
                if ((impliedClass == ObstacleClass.DynamicCarlike || impliedClass == ObstacleClass.DynamicStopped) && (obs.age - obs.offroadAge) > 10 && obs.offroadAge > 0)
                {
                    // label as not car like
                    impliedClass = ObstacleClass.DynamicNotCarlike;
                }

                obs.obstacleClass = impliedClass;

                foreach (Polygon poly in polys)
                {
                    Obstacle newObs = obs.ShallowClone();

                    newObs.obstaclePolygon = poly;

                    // determine what to do with the cluster
                    if (cluster.targetClass == SceneEstimatorTargetClass.TARGET_CLASS_CARLIKE && !cluster.isStopped)
                    {
                        // if the heading is valid, extrude the car polygon and predict forward
                        if (cluster.headingValid)
                        {
                            newObs.extrudedPolygon = ExtrudeCarPolygon(newObs.obstaclePolygon, cluster.relativeheading);
                        }
                    }

                    try {
                        newObs.mergePolygon = Polygon.ConvexMinkowskiConvolution(mergePolygon, newObs.AvoidancePolygon);
                    }
                    catch (Exception) {
                    }

                    obstacles.Add(newObs);
                }
            }

            return(obstacles);
        }
Esempio n. 3
0
        private List <Obstacle> ProcessUntrackedClusters(SceneEstimatorUntrackedClusterCollection clusters, List <Obstacle> trackedObstacles, Rect vehicleBox)
        {
            List <Obstacle> obstacles = new List <Obstacle>();

            SortedList <Obstacle, List <Coordinates> > point_splits = new SortedList <Obstacle, List <Coordinates> >();
            List <Coordinates> unclaimed_points = new List <Coordinates>(1500);

            foreach (SceneEstimatorUntrackedCluster cluster in clusters.clusters)
            {
                // clear out stored variables
                point_splits.Clear();
                unclaimed_points.Clear();

                // now determine if the point belongs to an old obstacle
                ObstacleClass targetClass;
                if (cluster.clusterClass == SceneEstimatorClusterClass.SCENE_EST_HighObstacle)
                {
                    targetClass = ObstacleClass.StaticLarge;
                }
                else
                {
                    targetClass = ObstacleClass.StaticSmall;
                }

                // only add points that are not within a tracked obstacle's extruded polygon
                for (int i = 0; i < cluster.points.Length; i++)
                {
                    Coordinates pt = cluster.points[i];
                    // iterate over all tracked cluster
                    bool did_hit = false;
                    if (useOccupancyGrid && Services.OccupancyGrid.GetOccupancy(pt) == OccupancyStatus.Free)
                    {
                        occupancyDeletedCount++;
                        did_hit = true;
                    }
                    else if (vehicleBox.IsInside(pt))
                    {
                        did_hit = true;
                    }
                    else if (trackedObstacles != null)
                    {
                        foreach (Obstacle trackedObs in trackedObstacles)
                        {
                            if (trackedObs.extrudedPolygon != null && trackedObs.extrudedPolygon.BoundingCircle.IsInside(pt) && trackedObs.extrudedPolygon.IsInside(pt))
                            {
                                did_hit = true;
                                break;
                            }
                        }
                    }

                    // if there was a hit, skip this point
                    if (!did_hit)
                    {
                        unclaimed_points.Add(pt);
                    }
                    //if (did_hit)
                    //  continue;

                    //Obstacle oldObstacle = FindIntersectingCluster(pt, targetClass, previousObstacles);

                    //if (oldObstacle != null) {
                    //  List<Coordinates> obstacle_points;
                    //  if (!point_splits.TryGetValue(oldObstacle, out obstacle_points)) {
                    //    obstacle_points = new List<Coordinates>(100);
                    //    point_splits.Add(oldObstacle, obstacle_points);
                    //  }

                    //  obstacle_points.Add(pt);
                    //}
                    //else {
                    //  unclaimed_points.Add(pt);
                    //}
                }

                // we've split up all the points appropriately
                // now construct the obstacles

                // we'll start with the obstacle belonging to an existing polygon
                //foreach (KeyValuePair<Obstacle, List<Coordinates>> split in point_splits) {
                //  if (split.Value != null && split.Value.Count >= 3) {
                //    // the obstacle will inherit most of the properties of the old obstacle
                //    Obstacle obs = new Obstacle();
                //    obs.age = split.Key.age+1;
                //    obs.obstacleClass = split.Key.obstacleClass;

                //    // don't bother doing a split operation on these clusters -- they have already been split
                //    obs.obstaclePolygon = Polygon.GrahamScan(split.Value);

                //    obstacles.Add(obs);
                //  }
                //}

                // handle the unclaimed points
                IList <Polygon> polygons = WrapAndSplit(unclaimed_points, split_area_threshold, split_length_threshold);

                foreach (Polygon poly in polygons)
                {
                    // create a new obstacle
                    Obstacle obs = new Obstacle();
                    obs.age           = 1;
                    obs.obstacleClass = targetClass;

                    obs.obstaclePolygon = poly;

                    obstacles.Add(obs);
                }
            }

            // test all old obstacles and see if they intersect any new obstacles
            // project the previous static obstacles to the current time frame

            if (processedObstacles != null)
            {
                try {
                    // get the relative transform
                    List <Obstacle> carryOvers   = new List <Obstacle>();
                    Circle          mergeCircle  = new Circle(merge_expansion_size, Coordinates.Zero);
                    Polygon         mergePolygon = mergeCircle.ToPolygon(24);

                    RelativeTransform transform = Services.RelativePose.GetTransform(processedObstacles.timestamp, clusters.timestamp);
                    foreach (Obstacle prevObs in processedObstacles.obstacles)
                    {
                        if (prevObs.obstacleClass == ObstacleClass.StaticLarge || prevObs.obstacleClass == ObstacleClass.StaticSmall)
                        {
                            prevObs.obstaclePolygon = prevObs.obstaclePolygon.Transform(transform);
                            prevObs.age++;

                            if (prevObs.age < 20)
                            {
                                Coordinates centroid = prevObs.obstaclePolygon.GetCentroid();
                                double      dist     = GetObstacleDistance(prevObs.obstaclePolygon);
                                double      angle    = centroid.ArcTan;
                                if (dist < 30 && dist > 6 && Math.Abs(centroid.Y) < 15 && Math.Abs(angle) < Math.PI / 2.0)
                                {
                                    try {
                                        prevObs.mergePolygon = Polygon.ConvexMinkowskiConvolution(mergePolygon, prevObs.obstaclePolygon);
                                        if (!TestIntersection(prevObs.mergePolygon, obstacles))
                                        {
                                            bool dropObstacle = false;
                                            for (int i = 0; i < prevObs.obstaclePolygon.Count; i++)
                                            {
                                                Coordinates pt = prevObs.obstaclePolygon[i];
                                                // iterate over all tracked cluster

                                                if (vehicleBox.IsInside(pt))
                                                {
                                                    dropObstacle = true;
                                                }
                                                else if (useOccupancyGrid && externalUseOccupancyGrid && Services.OccupancyGrid.GetOccupancy(pt) == OccupancyStatus.Free)
                                                {
                                                    dropObstacle = true;
                                                }
                                                else if (trackedObstacles != null)
                                                {
                                                    foreach (Obstacle trackedObs in trackedObstacles)
                                                    {
                                                        if (trackedObs.obstacleClass == ObstacleClass.DynamicCarlike)
                                                        {
                                                            Polygon testPoly = trackedObs.extrudedPolygon ?? trackedObs.mergePolygon;

                                                            if (testPoly != null && testPoly.BoundingCircle.IsInside(pt) && testPoly.IsInside(pt))
                                                            {
                                                                dropObstacle = true;
                                                                break;
                                                            }
                                                        }
                                                    }
                                                }

                                                if (dropObstacle)
                                                {
                                                    break;
                                                }
                                            }

                                            if (!dropObstacle)
                                            {
                                                carryOvers.Add(prevObs);
                                            }
                                        }
                                    }
                                    catch (Exception) {
                                    }
                                }
                            }
                        }
                    }

                    obstacles.AddRange(carryOvers);
                }
                catch (Exception) {
                }
            }

            // create the merge polygon for all these duder

            /*Circle mergeCircle = new Circle(merge_expansion_size, Coordinates.Zero);
             * Polygon mergePolygon = mergeCircle.ToPolygon(24);
             *
             * foreach (Obstacle obs in obstacles) {
             *      obs.mergePolygon = Polygon.ConvexMinkowskiConvolution(mergePolygon, obs.obstaclePolygon);
             * }*/

            return(obstacles);
        }
Esempio n. 4
0
        public ObstacleCollection GetProcessedObstacles(CarTimestamp timestamp, SAUDILevel saudi)
        {
            List <Obstacle> transformedObstacles = new List <Obstacle>();

            if (Services.StateProvider.GetVehicleState().speed < 4.5)
            {
                Obstacle leftObstacle  = GetSideObstacle(currentLeftSideObstacles);
                Obstacle rightObstacle = GetSideObstacle(currentRightSideObstacles);
                if (leftObstacle != null)
                {
                    transformedObstacles.Add(leftObstacle);
                }
                if (rightObstacle != null)
                {
                    transformedObstacles.Add(rightObstacle);
                }
            }

            ObstacleCollection processedObstacles = this.processedObstacles;

            if (processedObstacles != null)
            {
                if (transformedObstacles.Capacity < transformedObstacles.Count + processedObstacles.obstacles.Count)
                {
                    transformedObstacles.Capacity = transformedObstacles.Count + processedObstacles.obstacles.Count;
                }

                RelativeTransform transform = Services.RelativePose.GetTransform(processedObstacles.timestamp, timestamp);
                foreach (Obstacle obs in processedObstacles.obstacles)
                {
                    if (!Settings.IgnoreTracks || obs.obstacleClass == ObstacleClass.StaticLarge || obs.obstacleClass == ObstacleClass.StaticSmall)
                    {
                        Obstacle newObs = obs.ShallowClone();

                        if (saudi == SAUDILevel.L1)
                        {
                            if (obs.obstacleClass == ObstacleClass.StaticSmall && Math.Abs(newObs.AvoidancePolygon.GetArea()) < L1_area_threshold)
                            {
                                continue;
                            }
                        }
                        else if (saudi == SAUDILevel.L2)
                        {
                            if (obs.obstacleClass == ObstacleClass.StaticSmall)
                            {
                                continue;
                            }
                        }
                        else if (saudi == SAUDILevel.L3)
                        {
                            if (obs.obstacleClass == ObstacleClass.StaticSmall || obs.obstacleClass == ObstacleClass.StaticLarge || obs.obstacleClass == ObstacleClass.DynamicNotCarlike || obs.obstacleClass == ObstacleClass.DynamicUnknown)
                            {
                                continue;
                            }
                        }

                        if (newObs.cspacePolygon != null)
                        {
                            newObs.cspacePolygon = newObs.cspacePolygon.Transform(transform);
                        }
                        if (newObs.extrudedPolygon != null)
                        {
                            newObs.extrudedPolygon = newObs.extrudedPolygon.Transform(transform);
                        }
                        if (newObs.obstaclePolygon != null)
                        {
                            newObs.obstaclePolygon = newObs.obstaclePolygon.Transform(transform);
                        }
                        if (newObs.predictedPolygon != null)
                        {
                            newObs.predictedPolygon = newObs.predictedPolygon.Transform(transform);
                        }

                        transformedObstacles.Add(newObs);
                    }
                }
            }

            return(new ObstacleCollection(timestamp, transformedObstacles));
        }