Posicionamento de fusão multissensor (construção de mapa de nuvem de 3 pontos e posicionamento baseado em mapa) Detecção de loop ScanContext de 3 pontos

Posicionamento de fusão multissensor (construção de mapa de nuvem de 3 pontos e posicionamento baseado em mapa) Detecção de loop ScanContext de 3 pontos

Consulte o blog
para fazer o posicionamento de direção automática a partir do zero (11):
Avanço do sistema de direção automática de correção de loop fechado e combate real do projeto (4) Reconhecimento de cena 3D e detecção de loop fechado na construção de mapas de alta precisão de direção automática .
5) Use SC-LEGO-LOAM para construção de mapa de nuvem de pontos em grande escala e otimização de loop fechado

Código-fonte:
parte do código-fonte usado aqui é do github sc-lego-loam. A
estrutura geral do código é do código de correção de loop fechado do github tag11 de Rengan

ps: Porque sou um pouco branco, aqui é só expressar minhas próprias opiniões e aprender ideias, espero me corrigir

Idéia de código

Quadro geral

Vamos dar uma olhada na estrutura geral do
blog de referência a partir do zero para fazer o posicionador automático da unidade (IX): construir uma otimização
Insira a descrição da imagem aqui
da configuração do sistema para completar o módulo de detecção de loop para módulo

Insira a descrição da imagem aqui
Entre eles, o módulo de detecção de loop fechado contém duas partes: detecção de quadro de loop fechado e correspondência de nuvem de pontos
. Os blocos de código correspondentes são os seguintes:

    //闭环检测模块  (任乾)
    if (!DetectNearestKeyFrame(key_frame_index))
        return false;
        
	//点云配准 
    if (!CloudRegistration(key_frame_index))
        return false;

Ao chamar ScanContext, a detecção de loop da nuvem de ponto de quadro atual e da nuvem de ponto de quadro histórico é realizada, e key_frame_index (quadro de loop detectado) e yaw diff (ângulo de desvio de pose) são obtidos; então, o quadro de loop detectado é enviado para nuvem de ponto de CloudRegistration Módulo de registro

Escrita de código

Transplantado sc-lego-loam de código-fonte relevante e arquivos de biblioteca do ScanContext

Insira a descrição da imagem aqui
Adicionar arquivo de origem relacionado scan_context / Scancontext.cpp
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
adicionar arquivo de cabeçalho
Insira a descrição da imagem aqui

Observe que CMakeLists.txt adiciona

Adição de caminho nativo OpenCV

#本机OpenCV路径查看
locate   OpenCVConfig.cmake

Insira a descrição da imagem aqui

Chame principalmente duas funções em SC

scManager.detectLoopClosureID (); função de detecção de quadro de loopback, retorna -1 se não detectado, retorna o índice do quadro correspondente quando o quadro de loopback é detectado

scManager.makeAndSaveScancontextAndKeys (* raw_cloud_ptr); Salve a nuvem de pontos do quadro atual em tempo real para correspondência de loop

Função de escrita

SaveCurrentFrame (int pcd_idx) é
usado para salvar a nuvem de pontos do quadro atual, imitando o método de registro da nuvem de pontos, o pcd da nuvem de pontos do quadro atual é obtido do disco em tempo real e armazenado no ponteiro raw_cloud_ptr, e scManager.makeAndSaveScancontextAndKeys é chamado para salvar o quadro atual

DetectScanContext (int & key_frame_index, int pcd_idx)
detecta o quadro de loop, se verdadeiro, exibe o índice e a posição de desvio do quadro de loop; caso contrário, flase retorna -1

void LoopClosing::SaveCurrentFrame(int pcd_idx){
    
       
        // 读取并存储当前点云
    std::string file_path = key_frames_path_ + "/key_frame_" + std::to_string(pcd_idx) + ".pcd";
    CloudData::CLOUD_PTR raw_cloud_ptr(new CloudData::CLOUD());
     pcl::io::loadPCDFile(file_path, *raw_cloud_ptr);     //   raw_cloud_ptr  存储当前帧点云的point
    scManager.makeAndSaveScancontextAndKeys(*raw_cloud_ptr);     
}

// scan context  回环检测模块
int LoopClosing::DetectScanContext(int& key_frame_index,int pcd_idx) {
    
            
    SaveCurrentFrame(pcd_idx);

    auto detectResult = scManager.detectLoopClosureID();     //  进行回环帧的检测  first: nn index, second: yaw diff

    key_frame_index = detectResult.first;    // 获取回环帧的索引
    yawDiffRad = detectResult.second; // not use for v1 (because pcl icp withi initial somthing wrong...)
    
    return   key_frame_index;    //没有检测到返回 -1 ,检测到回环帧返回   对应帧 的索引 
}

Funções de chamada

Substitua a parte de detecção de loop de DetectNearestKeyFrame pelo Sr. Ren Qian, por exemplo: ScanContext faz um posicionamento aproximado. Depois de detectar o quadro de loop, envie o quadro de loop para o próximo módulo de registro de nuvem de ponto CloudRegistration (posicionamento preciso) para completar o posicionamento de loop inteiro. Consertar! ! !

bool LoopClosing::Update(const KeyFrame key_frame, const KeyFrame key_gnss) {
    
    
    has_new_loop_pose_ = false;

    all_key_frames_.push_back(key_frame);
    all_key_gnss_.push_back(key_gnss);

    int key_frame_index = 0;

   //  scan  context   回环检测 
    if (DetectScanContext(key_frame_index,key_frame.index)  == -1)       //  key_frame_index  闭环检测帧 ;   key_frame.index  当前帧数
        return false;

    //任乾  闭环检测模块
    // if (!DetectNearestKeyFrame(key_frame_index))
    //     return false;
    
    if (!CloudRegistration(key_frame_index))
        return false;

    has_new_loop_pose_ = true;
        return true;
}

Depuração de erros

Durante o processo de depuração, ocorre o motivo da leitura fora dos limites. O motivo é que, no módulo de correspondência de nuvem de pontos, a estratégia de registro adotada é o método Scan2Map. A construção do mapa exige a recuperação da fusão de quadros perto do quadro de anel. Se o índice for 0, o mapa é construído Quando o quadro próximo não existe, isso levará ao erro de apontar para fora dos limites.
Insira a descrição da imagem aqui

Parte modificada: adicionar JointMap

//越界保护
  if (i < 0 || i >= all_key_frames_.size( ) )    continue;

Insira a descrição da imagem aqui

efeito final

Use a detecção de loop DetectNearestKeyFrame de Rengan

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

rosservice call /optimize_map

Gerar optimized.txt
Insira a descrição da imagem aqui
para avaliação evo

evo_ape kitti ground_truth.txt optimized.txt -r full --plot --plot_mode xyz

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Detecção de loop usando DetectScanContext

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Através da comparação de dados, pode-se ver que há pouca diferença entre o módulo de detecção de loop do Sr. Ren Qian
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_41281151/article/details/109290982
Recomendado
Clasificación