Example #1
0
 public void ExtractObjectAttributes(LidarDetectedObject obj)
 {
     if (obj.AngleList.Count > 0)
     {
         obj.DistanceMoyenne = obj.DistanceList.Average();
         obj.Largeur         = (obj.AngleList.Max() - obj.AngleList.Min()) * obj.DistanceMoyenne;
     }
 }
        void ProcessLidarData(List <PolarPointRssi> ptList)
        {
            List <LidarDetectedObject> ObjetsSaillantsList        = new List <LidarDetectedObject>();
            List <LidarDetectedObject> BalisesCatadioptriqueList  = new List <LidarDetectedObject>();
            List <LidarDetectedObject> BalisesCatadioptriqueList2 = new List <LidarDetectedObject>();
            List <LidarDetectedObject> ObjetsProchesList          = new List <LidarDetectedObject>();
            List <LidarDetectedObject> ObjetsFondList             = new List <LidarDetectedObject>();
            List <LidarDetectedObject> ObjetsPoteauPossible       = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject = new LidarDetectedObject();

            //Opérations de traitement du signal LIDAR
            //ptList = PrefiltragePointsIsoles(ptList, 0.04);
            //ptList = MedianFilter(ptList, 5);

//            BalisesCatadioptriqueList = DetectionBalisesCatadioptriques(ptList, 3.6);
            BalisesCatadioptriqueList2 = DetectionBalisesCatadioptriquesParRssiEtTaille(ptList, 3.6);
            ObjetsProchesList          = DetectionObjetsProches(ptList, 0.17, 2.0, 0.2);

            //Affichage des résultats
            List <PolarPointListExtended> objectList = new List <PolarPointListExtended>();

            foreach (var obj in ObjetsProchesList)
            {
                PolarPointListExtended currentPolarPointListExtended = new PolarPointListExtended();
                currentPolarPointListExtended.polarPointList = new List <PolarPointRssi>();
                {
                    currentPolarPointListExtended.polarPointList.Add(new PolarPointRssi(obj.AngleMoyen, obj.DistanceMoyenne, 0));
                    currentPolarPointListExtended.type = ObjectType.Obstacle;
                    objectList.Add(currentPolarPointListExtended);
                }
            }
            foreach (var obj in BalisesCatadioptriqueList)
            {
                PolarPointListExtended currentPolarPointListExtended = new PolarPointListExtended();
                currentPolarPointListExtended.polarPointList = new List <PolarPointRssi>();
                {
                    currentPolarPointListExtended.polarPointList = obj.PtList;
                    currentPolarPointListExtended.type           = ObjectType.Balise;
                    objectList.Add(currentPolarPointListExtended);
                }
            }

            if (competition == GameMode.RoboCup)
            {
                ///On fait la recherche du rectangle vide le plus grand
                double tailleNoyau = 0.8;
                //var ptListFiltered = Dilatation(Erosion(ptList, tailleNoyau), tailleNoyau);
                //var ptListFiltered = Erosion(Dilatation(ptList, tailleNoyau), tailleNoyau);
                //var ptListFiltered = Dilatation(ptList, tailleNoyau);
                var ptListFiltered = Erosion(ptList, tailleNoyau);
                //var ptListFiltered = ptList;
                OnLidarProcessed(robotId, ptListFiltered);
            }
            OnLidarBalisesListExtracted(robotId, BalisesCatadioptriqueList2);
            OnLidarObjectProcessed(robotId, objectList);
        }
        private List <LidarDetectedObject> DetectionObjetsProches(List <PolarPointRssi> ptList, double distanceMin, double distanceMax, double tailleSegmentationObjet)
        {
            List <LidarDetectedObject> ObjetsProchesList = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject     = new LidarDetectedObject();;

            //Détection des objets proches
            var selectedPoints = ptList.Where(p => (p.Distance < distanceMax) && (p.Distance > distanceMin));
            List <PolarPointRssi> objetsProchesPointsList = (List <PolarPointRssi>)selectedPoints.ToList();

            //On segmente la liste de points sélectionnée en objets par la distance
            if (objetsProchesPointsList.Count() > 0)
            {
                currentObject = new LidarDetectedObject();
                currentObject.PtList.Add(objetsProchesPointsList[0]);
                double angleInitialObjet = objetsProchesPointsList[0].Angle;
                for (int i = 1; i < objetsProchesPointsList.Count; i++)
                {
                    if ((Math.Abs(objetsProchesPointsList[i].Angle - objetsProchesPointsList[i - 1].Angle) < Toolbox.DegToRad(2)) &&
                        (Math.Abs(objetsProchesPointsList[i].Distance - objetsProchesPointsList[i - 1].Distance) < 0.1) &&
                        (Math.Abs(objetsProchesPointsList[i].Angle - angleInitialObjet) * objetsProchesPointsList[i].Distance < tailleSegmentationObjet))
                    //Si les pts successifs sont distants de moins de x degrés et de moins de y mètres
                    //et que l'objet fait moins de tailleMax en largeur
                    {
                        //Le point est cohérent avec l'objet en cours, on ajoute le point à l'objet courant
                        currentObject.PtList.Add(objetsProchesPointsList[i]);
                    }
                    else
                    {
                        currentObject.ExtractObjectAttributes();
                        ObjetsProchesList.Add(currentObject);
                        currentObject = new LidarDetectedObject();
                        currentObject.PtList.Add(objetsProchesPointsList[i]);
                        angleInitialObjet = objetsProchesPointsList[i].Angle;
                    }
                }
                currentObject.ExtractObjectAttributes();
                ObjetsProchesList.Add(currentObject);
            }
            return(ObjetsProchesList);
        }
        //double seuilResiduLine = 0.03;

        //private List<LidarDetectedObject> DetectionObjetsFond(List<PolarPointRssi> ptList, double zoomCoeff)
        //{
        //    //Détection des objets de fond
        //    List<LidarDetectedObject> ObjetsFondList = new List<LidarDetectedObject>();
        //    LidarDetectedObject currentObject = new LidarDetectedObject();
        //    bool objetFondEnCours = false;

        //    for (int i = 1; i < ptList.Count; i++)
        //    {
        //        //On commence un objet de fond sur un front montant de distance
        //        if (ptList[i].Distance - ptList[i - 1].Distance > 0.06 * zoomCoeff)
        //        {
        //            currentObject = new LidarDetectedObject();
        //            currentObject.PtList.Add(ptList[i]);
        //            objetFondEnCours = true;
        //        }
        //        //On termine un objet de fond sur un front descendant de distance
        //        else if (ptList[i].Distance - ptList[i - 1].Distance < -0.12 * zoomCoeff && objetFondEnCours)
        //        {
        //            objetFondEnCours = false;
        //            if (currentObject.PtList.Count > 20)
        //            {
        //                currentObject.ExtractObjectAttributes();
        //                //Console.WriteLine("Résidu fond : " + currentObject.ResiduLineModel);
        //                //if (currentObject.ResiduLineModel < seuilResiduLine*2)
        //                {

        //                }
        //                    ObjetsFondList.Add(currentObject);
        //            }
        //        }
        //        //Sinon on reste sur le même objet
        //        else
        //        {
        //            if (objetFondEnCours)
        //            {
        //                currentObject.PtList.Add(ptList[i]);
        //            }
        //        }
        //    }

        //    return ObjetsFondList;
        //}

        private List <LidarDetectedObject> DetectionObjetsSaillants(List <PolarPointRssi> ptList, double seuilSaillance)
        {
            List <LidarDetectedObject> ObjetsSaillantsList = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject       = new LidarDetectedObject();;

            //Détection des objets saillants
            bool objetSaillantEnCours = false;

            for (int i = 1; i < ptList.Count; i++)
            {
                //On commence un objet saillant sur un front descendant de distance
                if (ptList[i].Distance - ptList[i - 1].Distance < -seuilSaillance)
                {
                    currentObject = new LidarDetectedObject();
                    currentObject.PtList.Add(ptList[i]);
                    objetSaillantEnCours = true;
                }
                //On termine un objet saillant sur un front montant de distance
                else if ((ptList[i].Distance - ptList[i - 1].Distance > seuilSaillance * 1.2) && objetSaillantEnCours)
                {
                    objetSaillantEnCours = false;
                    if (currentObject.PtList.Count > 20)
                    {
                        currentObject.ExtractObjectAttributes();
                        ObjetsSaillantsList.Add(currentObject);
                    }
                }
                //Sinon on reste sur le même objet
                else
                {
                    if (objetSaillantEnCours)
                    {
                        currentObject.PtList.Add(ptList[i]);
                    }
                }
            }

            return(ObjetsSaillantsList);
        }
        private List <LidarDetectedObject> DetectionBalisesCatadioptriques(List <PolarPointRssi> ptList, double distanceMax)
        {
            List <LidarDetectedObject> BalisesCatadioptriquesList = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject = new LidarDetectedObject();;

            //Détection des objets ayant un RSSI dans un intervalle correspondant aux catadioptres utilisés et proches
            //double maxRssiCatadioptre = 90;
            double minRssiCatadioptre = 50;
            var    selectedPoints     = ptList.Where(p => (p.Rssi >= minRssiCatadioptre) && (p.Distance < distanceMax));
            List <PolarPointRssi> balisesPointsList = (List <PolarPointRssi>)selectedPoints.ToList();

            //On segmente la liste de points sélectionnée en objets par la distance
            if (balisesPointsList.Count() > 0)
            {
                currentObject = new LidarDetectedObject();
                currentObject.PtList.Add(balisesPointsList[0]);
                for (int i = 1; i < balisesPointsList.Count; i++)
                {
                    if (Math.Abs(balisesPointsList[i].Angle - balisesPointsList[i - 1].Angle) < Toolbox.DegToRad(2)) //Si les pts successifs sont distants de moins de 1 degré
                    {
                        //Le point est cohérent avec l'objet en cours, on ajoute le point à l'objet courant
                        currentObject.PtList.Add(balisesPointsList[i]);
                    }
                    else
                    {
                        currentObject.ExtractObjectAttributes();
                        BalisesCatadioptriquesList.Add(currentObject);
                        currentObject = new LidarDetectedObject();
                        currentObject.PtList.Add(balisesPointsList[i]);
                    }
                }
                currentObject.ExtractObjectAttributes();
                BalisesCatadioptriquesList.Add(currentObject);
            }
            return(BalisesCatadioptriquesList);
        }
Example #6
0
        void ProcessLidarData(List <double> angleList, List <double> distanceList)
        {
            double        zoomCoeff             = 1.8;
            List <double> AngleListProcessed    = new List <double>();
            List <double> DistanceListProcessed = new List <double>();

            List <LidarDetectedObject> ObjetsSaillantsList  = new List <LidarDetectedObject>();
            List <LidarDetectedObject> ObjetsFondList       = new List <LidarDetectedObject>();
            List <LidarDetectedObject> ObjetsPoteauPossible = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject        = new LidarDetectedObject();

            //A enlever une fois le debug terminé
            for (int i = 1; i < angleList.Count; i++)
            {
                distanceList[i] *= zoomCoeff;
            }


            //Préfiltrage des points isolés : un pt dont la distance aux voisin est supérieur à un seuil des deux coté est considere comme isolé.
            double seuilPtIsole = 0.04 * zoomCoeff;   //0.03 car le Lidar a une précision intrinsèque de +/- 1 cm.

            for (int i = 1; i < angleList.Count - 1; i++)
            {
                if ((Math.Abs(distanceList[i - 1] - distanceList[i]) < seuilPtIsole) || (Math.Abs(distanceList[i + 1] - distanceList[i]) < seuilPtIsole))
                {
                    AngleListProcessed.Add(angleList[i]);
                    DistanceListProcessed.Add(distanceList[i]);
                }
            }

            angleList    = AngleListProcessed;
            distanceList = DistanceListProcessed;

            //Détection des objets saillants
            bool objetSaillantEnCours = false;

            for (int i = 1; i < angleList.Count; i++)
            {
                //On commence un objet saillant sur un front descendant de distance
                if (distanceList[i] - distanceList[i - 1] < -0.1 * zoomCoeff)
                {
                    currentObject = new LidarDetectedObject();
                    currentObject.AngleList.Add(angleList[i]);
                    currentObject.DistanceList.Add(distanceList[i]);
                    objetSaillantEnCours = true;
                }
                //On termine un objet saillant sur un front montant de distance
                if (distanceList[i] - distanceList[i - 1] > 0.15 * zoomCoeff)
                {
                    ExtractObjectAttributes(currentObject);
                    objetSaillantEnCours = false;
                    if (currentObject.AngleList.Count > 20)
                    {
                        ObjetsSaillantsList.Add(currentObject);
                    }
                }
                //Sinon on reste sur le même objet
                else
                {
                    if (objetSaillantEnCours)
                    {
                        currentObject.AngleList.Add(angleList[i]);
                        currentObject.DistanceList.Add(distanceList[i]);
                    }
                }
            }

            //Détection des objets saillants
            bool objetFondEnCours = false;

            for (int i = 1; i < angleList.Count; i++)
            {
                //On commence un objet de fond sur un front montant de distance
                if (distanceList[i] - distanceList[i - 1] > 0.1 * zoomCoeff)
                {
                    currentObject = new LidarDetectedObject();
                    currentObject.AngleList.Add(angleList[i]);
                    currentObject.DistanceList.Add(distanceList[i]);
                    objetFondEnCours = true;
                }
                //On termine un objet de fond sur un front descendant de distance
                if (distanceList[i] - distanceList[i - 1] < -0.15 * zoomCoeff)
                {
                    ExtractObjectAttributes(currentObject);
                    objetFondEnCours = false;
                    if (currentObject.AngleList.Count > 20)
                    {
                        ObjetsFondList.Add(currentObject);
                    }
                }
                //Sinon on reste sur le même objet
                else
                {
                    if (objetFondEnCours)
                    {
                        currentObject.AngleList.Add(angleList[i]);
                        currentObject.DistanceList.Add(distanceList[i]);
                    }
                }
            }

            foreach (var obj in ObjetsSaillantsList)
            {
                if (Math.Abs(obj.Largeur - 0.125 * zoomCoeff) < 0.1 * zoomCoeff)
                {
                    ObjetsPoteauPossible.Add(obj);
                }
            }

            List <PolarPointListExtended> objectList = new List <PolarPointListExtended>();

            foreach (var obj in ObjetsSaillantsList)
            {
                PolarPointListExtended currentPolarPointListExtended = new PolarPointListExtended();
                currentPolarPointListExtended.polarPointList = new List <PolarPoint>();
                //if (obj.Largeur > 0.05 && obj.Largeur < 0.5)
                {
                    for (int i = 0; i < obj.AngleList.Count; i++)
                    {
                        currentPolarPointListExtended.polarPointList.Add(new PolarPoint(obj.DistanceList[i], obj.AngleList[i]));
                        currentPolarPointListExtended.displayColor = System.Drawing.Color.Red;
                        currentPolarPointListExtended.displayWidth = 8;
                    }
                    objectList.Add(currentPolarPointListExtended);
                }
            }
            foreach (var obj in ObjetsPoteauPossible)
            {
                PolarPointListExtended currentPolarPointListExtended = new PolarPointListExtended();
                currentPolarPointListExtended.polarPointList = new List <PolarPoint>();
                //if (obj.Largeur > 0.05 && obj.Largeur < 0.5)
                {
                    for (int i = 0; i < obj.AngleList.Count; i++)
                    {
                        currentPolarPointListExtended.polarPointList.Add(new PolarPoint(obj.DistanceList[i], obj.AngleList[i]));
                        currentPolarPointListExtended.displayColor = System.Drawing.Color.Yellow;
                        currentPolarPointListExtended.displayWidth = 3;
                    }
                    objectList.Add(currentPolarPointListExtended);
                }
            }
            foreach (var obj in ObjetsFondList)
            {
                PolarPointListExtended currentPolarPointListExtended = new PolarPointListExtended();
                currentPolarPointListExtended.polarPointList = new List <PolarPoint>();
                //if (obj.Largeur > 0.05 && obj.Largeur < 0.5)
                {
                    for (int i = 0; i < obj.AngleList.Count; i++)
                    {
                        currentPolarPointListExtended.polarPointList.Add(new PolarPoint(obj.DistanceList[i], obj.AngleList[i]));
                        currentPolarPointListExtended.displayColor = System.Drawing.Color.Blue;
                        currentPolarPointListExtended.displayWidth = 6;
                    }
                    objectList.Add(currentPolarPointListExtended);
                }
            }
            //OnLidarProcessed(robotId, AngleListProcessed, DistanceListProcessed);

            OnLidarProcessed(robotId, angleList, distanceList);
            OnLidarObjectProcessed(robotId, objectList);
        }
        private List <LidarDetectedObject> DetectionBalisesCatadioptriquesParRssiEtTaille(List <PolarPointRssi> ptList, double distanceMax)
        {
            double minRssiBalise = 60;
            List <LidarDetectedObject> BalisesCatadioptriquesList = new List <LidarDetectedObject>();
            LidarDetectedObject        currentObject   = new LidarDetectedObject();;
            List <PolarPointRssi>      BalisePointList = new List <PolarPointRssi>();

            ////Détection des objets ayant un RSSI dans un intervalle correspondant aux catadioptres utilisés et proches
            ////double maxRssiCatadioptre = 90;
            //double minRssiCatadioptre = 60;
            //var selectedPoints = ptList.Where(p => (p.Rssi >= minRssiCatadioptre) && (p.Distance < distanceMax));
            //List<PolarPointRssi> balisesPointsList = (List<PolarPointRssi>)selectedPoints.ToList();

            //On détecte les max de RSSI supérieurs à un minRssiBalise
            List <int> maxRssiIndexList = new List <int>();

            if (ptList.Count() > 0)
            {
                for (int i = 1; i < ptList.Count - 1; i++)
                {
                    if (ptList[i].Rssi >= ptList[i - 1].Rssi && ptList[i].Rssi > ptList[i + 1].Rssi && ptList[i].Rssi > minRssiBalise)
                    {
                        maxRssiIndexList.Add(i);
                    }
                }
                //Gestion des cas de bord de tableau pour ne pas avoir de zone morte
                if (ptList[0].Rssi >= ptList[ptList.Count - 1].Rssi && ptList[0].Rssi > ptList[1].Rssi && ptList[0].Rssi > minRssiBalise)
                {
                    maxRssiIndexList.Add(0);
                }
                if (ptList[ptList.Count - 1].Rssi >= ptList[ptList.Count - 2].Rssi && ptList[ptList.Count - 1].Rssi > ptList[0].Rssi && ptList[ptList.Count - 1].Rssi > minRssiBalise)
                {
                    maxRssiIndexList.Add(ptList.Count - 1);
                }
            }


            //ON génère la liste des points des balises pour affichage de debug uniquement
            BalisePointList = new List <PolarPointRssi>();
            for (int i = 0; i < ptList.Count; i++)
            {
                PolarPointRssi pt = new PolarPointRssi(ptList[i].Angle, 0, ptList[i].Rssi);
                BalisePointList.Add(pt);
            }

            //On regarde la taille des objets autour des max de Rssi
            double seuilSaillance = 0.2;

            foreach (int indexPicRssi in maxRssiIndexList)
            {
                //On cherche à détecter les fronts montants de distance (distance qui augmente brutalement) autour des pics pour déterminer la taille des objets
                //On définit une taille max de recherche correspondant à 5 fois la taille d'une balise
                double tailleAngulaireBalisePotentielle = 0.15 / ptList[indexPicRssi].Distance;
                double incrementAngleLidar = ptList[1].Angle - ptList[0].Angle;
                //Défini la fenetre de recherche
                int indexSearchWindow = (int)(tailleAngulaireBalisePotentielle / incrementAngleLidar);

                int indexFrontMontantAngleSup = -1;
                int indexFrontMontantAngleInf = -1;
                //Détection des fronts montants coté des angles inférieurs à l'angle central
                int index      = indexPicRssi;
                int indexShift = 0; //Pour gérer les balises situées à l'angle 0
                while (index > indexPicRssi - indexSearchWindow)
                {
                    if (index - 1 < 0)
                    {
                        indexShift = ptList.Count();                      //Gestion des bords de tableau
                    }
                    BalisePointList[index + indexShift - 1].Distance = 5; //For debug display

                    if (Math.Abs(ptList[index + indexShift - 1].Distance - ptList[indexPicRssi].Distance) > seuilSaillance)
                    {
                        //On a un front montant coté des angles inférieurs à l'angle central
                        indexFrontMontantAngleInf = index + indexShift - 1;
                        break;
                    }
                    index--;
                }

                //Détection des fronts montants  coté des angles supérieurs à l'angle central
                index      = indexPicRssi;
                indexShift = 0; //Pour gérer les balises situées à l'angle 0
                while (index < indexPicRssi + indexSearchWindow)
                {
                    if (index + 1 >= ptList.Count)
                    {
                        indexShift = -ptList.Count();                     //Gestion des bords de tableau
                    }
                    BalisePointList[index + indexShift + 1].Distance = 6; //For debug display

                    if (Math.Abs(ptList[index + indexShift + 1].Distance - ptList[indexPicRssi].Distance) > seuilSaillance)
                    {
                        //On a un front montant coté des angles supérieurs à l'angle central
                        indexFrontMontantAngleSup = index + indexShift + 1;
                        break;
                    }
                    index++;
                }
                if (indexFrontMontantAngleInf >= 0 && indexFrontMontantAngleSup >= 0)
                {
                    //On a deux fronts montants de part et d'autre du pic, on regarde la taille de l'objet
                    double tailleObjet = (ptList[indexFrontMontantAngleSup].Angle - ptList[indexFrontMontantAngleInf].Angle)
                                         * (ptList[indexFrontMontantAngleSup].Distance + ptList[indexFrontMontantAngleInf].Distance + ptList[indexPicRssi].Distance) / 3;
                    //if(tailleObjet>0.05&& tailleObjet<0.25)
                    {
                        //On a probablement un catadioptre de type balise Eurobot !
                        currentObject = new LidarDetectedObject();

                        if (indexFrontMontantAngleInf < indexFrontMontantAngleSup)
                        {
                            for (int i = indexFrontMontantAngleInf + 1; i < indexFrontMontantAngleSup - 1; i++) //Décalages pour éviter de mettre une distance erronnée dans les amas de points
                            {
                                currentObject.PtList.Add(ptList[i]);
                                BalisePointList[i].Distance = 10; //For debug display
                            }
                            currentObject.ExtractObjectAttributes();
                            BalisesCatadioptriquesList.Add(currentObject);
                        }
                        else  //Gestion des objets coupés en deux par l'angle 0
                        {
                            for (int i = indexFrontMontantAngleInf + 1; i < ptList.Count; i++) //Décalages pour éviter de mettre une distance erronnée dans les amas de points
                            {
                                currentObject.PtList.Add(ptList[i]);
                                BalisePointList[i].Distance = 10; //For debug display
                            }

                            for (int i = 0; i < indexFrontMontantAngleSup - 1; i++) //Décalages pour éviter de mettre une distance erronnée dans les amas de points
                            {
                                currentObject.PtList.Add(new PolarPointRssi(ptList[i].Angle + 2 * Math.PI, ptList[i].Distance, ptList[i].Rssi));
                                BalisePointList[i].Distance = 10; //For debug display
                            }
                            currentObject.ExtractObjectAttributes();
                            BalisesCatadioptriquesList.Add(currentObject);
                        }
                    }
                }
            }

            OnLidarBalisePointListForDebug(robotId, BalisePointList);

            return(BalisesCatadioptriquesList);
        }
        private List <PolarPointRssi> Erosion(List <PolarPointRssi> ptList, double rayon)
        {
            int originalSize = ptList.Count;
            /// On construit une liste de points ayant le double du nombre de points de la liste d'origine, de manière
            /// à avoir un recoupement d'un tour complet
            List <PolarPointRssi> ptListExtended = new List <PolarPointRssi>();

            for (int i = (int)(originalSize / 2); i < originalSize; i++)
            {
                ptListExtended.Add(new PolarPointRssi(ptList[i].Angle - 2 * Math.PI, ptList[i].Distance, ptList[i].Rssi));
            }
            for (int i = 0; i < originalSize; i++)
            {
                ptListExtended.Add(new PolarPointRssi(ptList[i].Angle, ptList[i].Distance, ptList[i].Rssi));
            }
            for (int i = 0; i < (int)(originalSize / 2); i++)
            {
                ptListExtended.Add(new PolarPointRssi(ptList[i].Angle + 2 * Math.PI, ptList[i].Distance, ptList[i].Rssi));
            }

            ptList = ptListExtended;

            /// On déclare une liste pour les points de sortie.
            /// L'initialisation manuelle est obligatoire, la copie ne marche pas car elle se fait par référence,
            /// donc tout modification au tableau dilaté se reporterait dans le tableau initial
            List <PolarPointRssi> ptListEroded           = new List <PolarPointRssi>();
            List <int>            ptListErodedbyObjectId = new List <int>();

            for (int i = 0; i < ptList.Count; i++)
            {
                ptListEroded.Add(new PolarPointRssi(ptList[i].Angle, ptList[i].Distance, ptList[i].Rssi));
                ptListErodedbyObjectId.Add(0);
            }
            double resolutionAngulaire = 2 * Math.PI / ptList.Count;

            /// On effectue une segmentation en objet connexes, de manière à éviter les effets de bords
            /// d'érosion au voisinnage des objets en saillie.
            /// On effetue donc l'érosion en notant pour chaque angle quel est l'objet ayant contribué à l'érosion
            /// Une fois l'érosion terminée, on retire, en passant la distance pt à l'infini,
            /// les points érodé par un objet différent de celui dans lequel ils sont dans l'ombre.
            ///

            ///On commence par la segmentation en objets
            List <LidarDetectedObject> lidarSceneSegmentation = new List <LidarDetectedObject>();
            LidarDetectedObject        objet = new LidarDetectedObject();
            double seuilDetectionObjet       = 0.2;

            objet.PtList.Add(ptList[0]);
            for (int i = 1; i < ptList.Count; i++)
            {
                if (Math.Abs(ptList[i].Distance - ptList[i - 1].Distance) < seuilDetectionObjet)
                {
                    ///Si la distance entre deux points successifs n'est pas trop grande, ils appartiennent au même objet
                    objet.PtList.Add(ptList[i]);
                }
                else
                {
                    //Sinon, on crée un nouvel objet
                    lidarSceneSegmentation.Add(objet);
                    objet = new LidarDetectedObject();
                    objet.PtList.Add(ptList[i]);
                }
            }

            int numPtCourant = 0;

            for (int n = 0; n < lidarSceneSegmentation.Count; n++)
            {
                /// On itère sur tous les objets dans l'ordre
                ///
                var obj       = lidarSceneSegmentation[n];
                var objPtList = obj.PtList;
                for (int k = 0; k < objPtList.Count; k++)
                {
                    var    pt = ptList[numPtCourant];
                    double erosionAngulaire = Math.Atan2(rayon, pt.Distance);
                    int    nbPasAngulaire   = (int)(erosionAngulaire / resolutionAngulaire);
                    int    borneInf         = Math.Max(0, numPtCourant - nbPasAngulaire);
                    int    borneSup         = Math.Min(numPtCourant + nbPasAngulaire, ptList.Count - 1);

                    for (int j = borneInf; j <= borneSup; j++)
                    {
                        /// Pour avoir une formule qui fonctionne aux petites distances avec un grand rayon d'érosion,
                        /// il faut utiliser les lois des cosinus
                        double a = 1;
                        double b = -2 * ptList[numPtCourant].Distance * Math.Cos((j - numPtCourant) * resolutionAngulaire);
                        double c = ptList[numPtCourant].Distance * ptList[numPtCourant].Distance - rayon * rayon;

                        double discrimant     = b * b - 4 * a * c;
                        double distanceErodee = (-b + Math.Sqrt(discrimant)) / (2 * a);
                        double distanceSeuil  = (-b - Math.Sqrt(discrimant)) / (2 * a);

                        /// Version simple
                        if (distanceErodee >= ptListEroded[j].Distance)
                        {
                            ptListEroded[j].Distance  = distanceErodee;
                            ptListErodedbyObjectId[j] = n;
                        }
                    }
                    numPtCourant++;
                }
            }

            /// On fait une seconde passe pour retirer tous les points érodés par un objet autre que celui
            /// qui les masque.
            numPtCourant = 0;
            for (int n = 0; n < lidarSceneSegmentation.Count; n++)
            {
                /// On itère sur tous les objets dans l'ordre
                var obj       = lidarSceneSegmentation[n];
                var objPtList = obj.PtList;
                for (int k = 0; k < objPtList.Count; k++)
                {
                    if (ptListErodedbyObjectId[numPtCourant] != n)
                    {
                        ptListEroded[numPtCourant].Distance = double.PositiveInfinity;
                    }
                    numPtCourant++;
                }
            }

            //    for (int i = 0; i < ptList.Count; i++)
            //{
            //    var pt = ptList[i];
            //    double erosionAngulaire = Math.Atan2(rayon, pt.Distance);
            //    int nbPasAngulaire = (int)(erosionAngulaire / resolutionAngulaire);
            //    int borneInf = Math.Max(0, i - nbPasAngulaire);
            //    int borneSup = Math.Min(i + nbPasAngulaire, ptList.Count - 1);

            //    for (int j = borneInf; j <= borneSup; j++)
            //    {
            //        /// Pour avoir une formule qui fonctionne aux petites distances avec un grand rayon d'érosion,
            //        /// il faut utiliser les lois des cosinus
            //        double a = 1;
            //        double b = -2 * ptList[i].Distance * Math.Cos((j - i) * resolutionAngulaire);
            //        double c = ptList[i].Distance * ptList[i].Distance - rayon * rayon;

            //        double discrimant = b * b - 4 * a * c;
            //        double distanceErodee = (-b + Math.Sqrt(discrimant)) / (2 * a);
            //        double distanceSeuil = (-b - Math.Sqrt(discrimant)) / (2 * a);

            //        /// Version simple
            //        ptListEroded[j].Distance = Math.Max(ptListEroded[j].Distance, distanceErodee);

            //        /// Variante permettant d'exclure les occlusions de la liste  érodée,
            //        /// de manière à ne pas créer d'objet virtuel derrière les objets masqués.
            //        //if (ptList[j].Distance > distanceSeuil - rayon)
            //        //    ptListEroded[j].Distance = Math.Max(ptListEroded[j].Distance, distanceErodee);
            //        //else
            //        //    ptListEroded[j].Distance = double.PositiveInfinity;

            //    }
            //}
            //return ptListEroded;
            return(ptListEroded.ToList().GetRange((int)(originalSize / 2), originalSize));
        }