Lectura de código fuente ORB-SLAM2 (2)

Lectura de código fuente ORB-SLAM2 (2)

Subproceso de mapeo local

Tomamos el programa de muestra mono_tim.cc como ejemplo En este ejemplo, primero necesitamos construir el sistema ORB-SLAM

// Create SLAM system. It initializes all system threads and gets ready to process frames.
//构建SLAM系统,调用有参构造函数,传入参数为:ORB字典,参数配置文件,相机类型
ORB_SLAM2::System SLAM(argv[1], argv[2], ORB_SLAM2::System::MONOCULAR, true);

En la definición de la función del sistema, se inicializan subprocesos como Local Mapping y Loop Closing. Para obtener más información, consulte nuestro blog anterior.

En el blog anterior, se introdujo el hilo principal de ORB-SLAM: hilo de seguimiento, hoy presentaré principalmente los dos hilos restantes

//Initialize the Local Mapping thread and launch
mpLocalMapper = new LocalMapping(mpMap, mSensor==MONOCULAR);
mptLocalMapping = new thread(&ORB_SLAM2::LocalMapping::Run,mpLocalMapper);

Se puede ver que la inicialización del hilo Local Mapping se implementa principalmente a través de la función ORB_SLAM2::LocalMapping::Run( ), echemos un vistazo a la implementación de esta función

void LocalMapping::Run()
{
    
    

    mbFinished = false;

    while(1)
    {
    
    
        // Tracking will see that Local Mapping is busy
        SetAcceptKeyFrames(false);

        // Check if there are keyframes in the queue
        if(CheckNewKeyFrames())     //若队列中有新的关键帧
        {
    
    
            // BoW conversion and insertion in Map
            ProcessNewKeyFrame();

            // Check recent MapPoints
            MapPointCulling();

            // Triangulate new MapPoints
            CreateNewMapPoints();

            if(!CheckNewKeyFrames())    //队列中的关键帧处理完毕
            {
    
    
                //检查Current KF的Covisible KFS,对重复构建的MapPoints进行融合
                // Find more matches in neighbor keyframes and fuse point duplications
                SearchInNeighbors();
            }

            mbAbortBA = false;

            if(!CheckNewKeyFrames() && !stopRequested())    //没有新的KF且无停止LoopClosing线程的请求
            {
    
    
                // Local BA
                if(mpMap->KeyFramesInMap()>2)   //地图中的关键帧要大于两帧
                    Optimizer::LocalBundleAdjustment(mpCurrentKeyFrame,&mbAbortBA, mpMap);

                //剔除冗余关键帧
                // Check redundant local Keyframes
                KeyFrameCulling();
            }

            //筛选后的关键帧插入LoopClosing线程
            mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame);
        }
        else if(Stop())
        {
    
    
            //确保KF筛选完成
            // Safe area to stop
            while(isStopped() && !CheckFinish())
            {
    
    
                usleep(3000);
            }
            if(CheckFinish())
                break;
        }

        //在收到请求后可以删除新添加的KF和MapPoints
        ResetIfRequested();

        // Tracking will see that Local Mapping is busy
        SetAcceptKeyFrames(true);

        //等待插入完成
        if(CheckFinish())
            break;

        usleep(3000);
    }

    SetFinish();
}

Podemos mirar el programa contra esta imagen de nuevo.

Por favor agregue la descripción de la imagen

Se puede ver que los pasos principales son:

  1. Reciba el KF insertado desde el subproceso de seguimiento y realice el preprocesamiento.
    Cuando el subproceso de seguimiento determina que se inserte un KF, en realidad no completa la acción de insertar el KF en el mapa. Al insertar un KF en el mapa, debe hacerlo Mucho trabajo de actualización
    Actualizar el gráfico de covisibilidad;
    actualizar el árbol de expansión:
    calcular el BoW del nuevo KF
  2. Elimine MapPoints de mala calidad Los MapPoints
    almacenados en Map deben ser de alta calidad (buen seguimiento, triangulación correcta), por lo que es necesario tomar algunas medidas aquí para eliminar los MapPoints de mala calidad.
  3. Generar nuevos MapPoints a través de la triangulación
    ORB-SLAM coincidirá con los FeaturePoints en el KF actual que no coinciden con los MapPoints existentes, y sus KF covisibles tampoco coinciden con los FeaturePoints que coinciden con los MapPoints existentes.
    Si coinciden, puede A través de la triangulación, un se genera un nuevo MapPoint (la posición, el paralaje, el error de reproyección y la consistencia de la escala deben verificarse después de la generación)
    . La coincidencia entre este FeaturePoint y FeaturePoint se logra a través de la búsqueda BoW.
    Después de generar un nuevo MapPoint a través de dos KF, y también verifique si aparece en otros KF. Entonces, para proyectar el MapPoint a otros KF Covisibles y hacer coincidir sus FeaturePoints
    , si coinciden, vincule el MapPoint con el FeaturePoint de ese KF
  4. Optimización BA del mapa local Optimización BA
    del KF actual y sus KF covisibles y todos los MapPoints que observan
  5. Elimine los fotogramas clave locales redundantes
    En el subproceso de seguimiento, ORB-SLAM inserta una gran cantidad de KF en el mapa en condiciones muy flexibles, pero obviamente el mapa no puede mantener tantos KF de forma permanente, lo que hará que el mapa sea demasiado grande y aumente considerablemente la carga computacional. de varios BA, por lo que se debe eliminar cierta información redundante.
    Si hay algún KF en el KF actual y sus KF covisibles, el 90% de los MapPoints que observa pueden ser utilizados por al menos otros 3 (la misma escala. o mejor) Se observan los KF, luego la información de este KF se considera redundante y se elimina. El propósito de esto es mantener la cantidad de KF en el Mapa no demasiado grande, y en un escenario con una cierta escala, la cantidad de KF en el Mapa no debería aumentar sin un límite superior, lo que también conduce a reducir la carga. de optimización BA.

El diagrama de flujo del programa correspondiente es el siguiente:

Por favor agregue la descripción de la imagen

Hilo de cierre de lazo

El subproceso de cierre de bucle se implementa principalmente a través de la función ORB_SLAM2::LoopClosing::Run()

mpLoopCloser = new LoopClosing(mpMap, mpKeyFrameDatabase, mpVocabulary, mSensor!=MONOCULAR);
mptLoopClosing = new thread(&ORB_SLAM2::LoopClosing::Run, mpLoopCloser);

Las funciones específicas son las siguientes:

void LoopClosing::Run()
{
    
    
    mbFinished =false;

    while(1)
    {
    
    
        // Check if there are keyframes in the queue
        if(CheckNewKeyFrames())
        {
    
    
            // Detect loop candidates and check covisibility consistency
            if(DetectLoop())
            {
    
    
               // 计算SIM3或SE3,确定最终的Loop KF
               // Compute similarity transformation [sR|t]
               // In the stereo/RGBD case s=1
               if(ComputeSim3())
               {
    
    
                   // Perform loop fusion and pose graph optimization
                   CorrectLoop();
               }
            }
        }       

        ResetIfRequested();

        if(CheckFinish())
            break;

        usleep(5000);
    }

    SetFinish();
}

Aquí hay otra foto:

Por favor agregue la descripción de la imagen

El hilo de cierre de bucle se puede dividir en dos pasos:

  1. Detección de bucle: Detección de bucle
  2. Corrección de bucle: Corrección de bucle
  • La función DetectLoop( ) detecta un lote de Candidatos KF
  • La función ComputeSim3( ) calcula la transformación de similitud entre KF actual y KF candidato, y determina el KF de bucle final en consecuencia.
  • La función CorrectLoop( ) realiza la corrección de loopback

Después de completar todos los pasos anteriores, la precisión ya es muy alta, pero ORB-SLAM2 aún elige realizar un Global BA al final para agregar la guinda del pastel (este paso no parece estar en ORB-SLAM1)

Tenga en cuenta que para no afectar el trabajo de los 3 subprocesos principales, aquí se crea un 4.º subproceso para Global BA, pero Global BA puede interrumpirse en cualquier momento y solo se ejecutará cuando el sistema esté particularmente inactivo.

El diagrama de flujo del programa correspondiente es el siguiente:

Por favor agregue la descripción de la imagen

referencia principal

Aprendizaje de código y papel ORB-SLAM2 - Subproceso LocalMapping - MingruiYu - Blog Park (cnblogs.com)

ORB-SLAM2 Aprendizaje de papel y código - LoopClosing Thread - MingruiYu - Blog Park (cnblogs.com)

Si hay alguna infracción, póngase en contacto para eliminar

Supongo que te gusta

Origin blog.csdn.net/qq_34935373/article/details/124027369
Recomendado
Clasificación