自定义语义点云可视化渲然,多版本VTK库冲突导致段错误(核心已转储),已解决。

自己定义了一个点云结构PointXYZIL,定义格式如下

#ifndef PCL_NO_PRECOMPILE
#define PCL_NO_PRECOMPILE

#include <pcl/point_types.h>
#include <pcl/pcl_macros.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>

struct EIGEN_ALIGN16 PointXYZIL    // 强制SSE填充以获得正确的内存对齐  
{
	PCL_ADD_POINT4D;                  // 添加XYZ+填充类型的首选方式
    PCL_ADD_INTENSITY;                //添加强度
	uint8_t label;                    //添加语义
	PCL_MAKE_ALIGNED_OPERATOR_NEW;     // 确保新的分配器内存是对齐的
};

POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZIL, // 注册点类型宏 XYZ + "test" (as fields)
	(float, x, x)
	(float, y, y)
	(float, z, z)
	(uint8_t, label, label)
)
#endif 

然后将自定义的点云保存成pcd文件,现在把读取pcd文件,并想根据语义信息的不同给点云上色,写了下面一段程序:

#include<pcl/visualization/pcl_visualizer.h>
#include<pointxyzil.h>
#include <pcl/visualization/point_cloud_geometry_handlers.h>
#include <pcl/visualization/impl/point_cloud_geometry_handlers.hpp>
#include<iostream>

int color_map[5][3] ={{255,0,0},{0,255,0},{0,0,255},{0,255,255},{255,255,0}};
int main(){
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgb_pointcloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::PointCloud<PointXYZIL>::Ptr semantic_pointcloud (new pcl::PointCloud<PointXYZIL>());
    pcl::PCDReader pcd_reader;
    pcd_reader.read("/home/lho/slam_ws/src/LVI-SAM/result/semantic_map.pcd",*semantic_pointcloud);
    //因为自定义点云没有对应的可视化函数,所以先将其转换成pcl中PointXYZRGB格式,然后再对其渲染着色
    for(std::size_t i=0;i<semantic_pointcloud->size();i++){
        pcl::PointXYZRGB point;
        int label = semantic_pointcloud->points[i].label;
        int index = label % 4;
        int r = color_map[index][0];
        int g = color_map[index][1];
        int b = color_map[index][2];
        point.x = semantic_pointcloud->points[i].x;
        point.y = semantic_pointcloud->points[i].y;
        point.z = semantic_pointcloud->points[i].z;
        point.r = uint8_t(r);
        point.g = uint8_t(g);
        point.b = uint8_t(b);
        rgb_pointcloud->push_back(std::move(point));
    }
    pcl::visualization::PCLVisualizer viewer;
    viewer.setBackgroundColor(0, 0, 0);
    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb_color_handler(rgb_pointcloud);
    viewer.addPointCloud<pcl::PointXYZRGB>(rgb_pointcloud,rgb_color_handler,"RGB PointCloud");//运行到这里报错
    viewer.spin(); 
    return 0;
}

但是运行到 viewer.addPointCloudpcl::PointXYZRGB(rgb_pointcloud,rgb_color_handler,“RGB PointCloud”);时,出现段错误 (核心已转储)。网上找了很久,也没有找到解决办法,所以决定自己一步步Debug。因为我是经常使用vscode,所以我就用它自带的gdb来Debug。

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ - Build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            //需要Debug的程序的路径
            "program": "${workspaceFolder}/build/pointcloud_visualiser",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            // gdb路径,
            "miDebuggerPath": "/usr/bin/gdb"
            //preLaunch这个参数我注释掉了,这个参数的作用是,每次Debug之前自动生成可执行程序
            //参数的内容需要和task.json(编译程序的配置文件)的中label参数内容一致
            //但是我自己是手动用CMakeLists.txt编译的,所以我注释掉了,意思是每次Debug就直接运行我已经生成的程序
            //但是如果你源码有变动一定要重新编译一下,不然Debug运行的程序就和源码不匹配了
            //CMakeLists.txt记得加set(CMAKE_BUILD_TYPE "Debug"),用Debug模式编译,不然肯能不能用gdb Debug
            //"preLaunchTask": "build",
        }
    ]

}

然后通过打断点的形式进入 viewer.addPointCloudpcl::PointXYZRGB(rgb_pointcloud,rgb_color_handler,“RGB PointCloud”);函数内部。通过层层跳转,终于进入到报错的地方,是vtk一个库函数报错。

void vtkObject::SetObjectName(const std::string& objectName)
{
  vtkDebugMacro(<< vtkObjectBase::GetObjectDescription() << "set object name to '" << objectName
                << "'");

  this->ObjectName = objectName;//报错的地方
}

然后在程序中打了一个Log Message断点,打印函数参数objectName,然后发现是无法访在这里插入代码片问的内存区域,所以才导致了段错误。然后我怀疑它可能就是空的,所以我决定返回上级,看看传入的参数是不是正确。
Log Message 断点通过Debug模式的CALL STACK找到上一级的函数,发现上级函数根本没有调用这个函数,不知道怎么跳转到SetObjectName函数的。
在这里插入图片描述
找了好久才发现,他们不是同一个版本的库,头文件是7.1,源文件是9.2.2,我怀疑是库版本错误导致的。
在这里插入图片描述
所以我在CMakeLists.txt中加了下面一行,指定vtk库的版本,然后完美解决

find_package(VTK 9.2.2 EXACT REQUIRED)

自定义的语义点云,渲染上颜色效果如下图所示。
在这里插入图片描述
总结一下,这个是一个由于多版本第三方库导致的问题,当我们运行的程序多的时候,电脑上有时候不可避免要装多个版本的第三方库,所以在编译的时候,一定要指定好第三方库的版本,如下面所示。建议安装第三方库的是手动设置 CAMKE_INSTALL_PREFIX 参数,将第三方库安装到一个包中,这样方便管理。Linux文件管理方式和Windows是不一样的,windows是把同一个库装到一个包中,Linux是按照文件类型进行分类的,比如把不同的库的头文件都放到 /usr/include中,把库文件放到 /usr/lib中,比较杂。我一般是喜欢把第三方库都安装到一个包中,路径一般是/usr/local下。

find_package(VTK 9.2.2 EXACT REQUIRED)
或者
set(VTK_DIR /usr/local/vtk922)#指定库路径
find_package(VTK REQUIRED)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值