【问题标题】:Visualize PCD containing custom double point structure可视化包含自定义双点结构的 PCD
【发布时间】:2020-04-21 10:13:51
【问题描述】:

我创建了一个自定义双点类型,用于将点位置存储在 PCD 文件中。我需要双精度数据类型,因为我的点位于全局坐标中并且具有非常大的值(顺序为 10^6 到 10^7)并且需要良好的精度。由于值很大并且默认的 FLOAT32 精度有限,因此在可视化过程中也可以看到相当多的数据近似值。

我通过使用我拥有的数据包中来自 GPS 的初始全球参考坐标转换原始点云来创建此 PCD。我使用的是 15 点精度。

我创建了一个单独的脚本来可视化这个自定义点型 PCD。但是通过视觉比较,我看不出 FLOAT32 和双数据类型 PCD 之间有任何显着差异。

Raw_float_pcd_visualization

Transformed_float_pcd_visualization

Transformed_double_pcd_visualization

您可以看到transformed_double 和transformed_float PCD 非常相似和近似。与这两者相比,raw_float PCD 相当不错。

我附上 PCD 文件以供参考:

raw_float

transformed_float

transformed_double

我认为我在加载点云时跳过了一些内容,并且需要进行一些更改才能以双点精度可视化点。

我使用 pcl_tools 中的“pcl_viewer”来可视化 FLOAT 类型的 PCD。

自定义 DOUBLE 点结构 PCD 的可视化代码:

#define PCL_NO_PRECOMPILE
#include <iostream>

// #include "double_viz/pcl_double.h"
#include <pcl-1.7/pcl/common/common.h>
#include <pcl-1.7/pcl/io/pcd_io.h>
#include <pcl-1.7/pcl/visualization/pcl_visualizer.h>
#include <pcl-1.7/pcl/console/parse.h>
#include <pcl-1.7/pcl/point_cloud.h>
#include <pcl-1.7/pcl/point_types.h>

namespace pcl
{
  #define PCL_ADD_UNION_POINT4D_DOUBLE \
    union EIGEN_ALIGN16 { \
      double data[4]; \
      struct { \
        double x; \
        double y; \
        double z; \
      }; \
    };

  struct _PointXYZDouble
  {
    PCL_ADD_UNION_POINT4D_DOUBLE; // This adds the members x,y,z which can also be accessed using the point (which is float[4])

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  };

  struct EIGEN_ALIGN16 PointXYZDouble : public _PointXYZDouble
  {
    inline PointXYZDouble (const _PointXYZDouble &p)
    {
      x = p.x; y = p.y; z = p.z; data[3] = 1.0;
    }

    inline PointXYZDouble ()
    {
      x = y = z = 0.0;
      data[3] = 1.0;
    }

    inline PointXYZDouble (double _x, double _y, double _z)
    {
      x = _x; y = _y; z = _z;
      data[3] = 1.0;
    }

    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  };
}

  POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::_PointXYZDouble,
    (double, x, x)
    (double, y, y)
    (double, z, z)
  )
  POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::PointXYZDouble, pcl::_PointXYZDouble)


// This function displays the help
void
showHelp(char * program_name)
{
  std::cout << std::endl;
  std::cout << "Usage: " << program_name << " cloud_filename.[pcd]" << std::endl;
  std::cout << "-h:  Show this help." << std::endl;
}

// This is the main function
int
main (int argc, char** argv)
{

  // Show help
  if (pcl::console::find_switch (argc, argv, "-h") || pcl::console::find_switch (argc, argv, "--help")) 
  {
    showHelp (argv[0]);
    return 0;
  }

  // Fetch point cloud filename in arguments | Works with PCD
  std::vector<int> filenames;

  if (filenames.size () != 1)  
  {
    filenames = pcl::console::parse_file_extension_argument (argc, argv, ".pcd");

    if (filenames.size () != 1) 
    {
      showHelp (argv[0]);
      return -1;
    } 
  }

  // Load file | Works with PCD and PLY files
  pcl::PointCloud<pcl::PointXYZDouble>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZDouble> ());

    if (pcl::io::loadPCDFile (argv[filenames[0]], *source_cloud) < 0)  
    {
      std::cout << "Error loading point cloud " << argv[filenames[0]] << std::endl << std::endl;
      showHelp (argv[0]);
      return -1;
    }
  // Visualization
//   printf(  "\nPoint cloud colors :  white  = original point cloud\n"
//       "                        red  = transformed point cloud\n");
  pcl::visualization::PCLVisualizer viewer ("Visualize double PCL");

   // Define R,G,B colors for the point cloud
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZDouble> source_cloud_color_handler (source_cloud, 100, 100, 100);
  // We add the point cloud to the viewer and pass the color handler
  viewer.addPointCloud (source_cloud, source_cloud_color_handler, "original_cloud");

  viewer.addCoordinateSystem (1.0, "cloud", 0);
  viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1, "original_cloud");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original_cloud");
  viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 1, "original_cloud");
  //viewer.setPosition(800, 400); // Setting visualiser window position

  while (!viewer.wasStopped ()) // Display the visualiser until 'q' key is pressed
  { 
    viewer.spinOnce ();
  }

  return 0;
}

【问题讨论】:

    标签: double visualization precision point-cloud-library point-clouds


    【解决方案1】:

    raw_float文件中,大小字段被定义为每个4字节:SIZE 4 4 4 4, 要读取为 double,它应该是 SIZE 8 8 8 8

    在您当前的实现中,每个字段都被读取为 Float32

    【讨论】:

    • 很抱歉给您带来了困惑。我使用raw_float PCD 生成transformed_floattransformed_double PCD。转换后我失去了点精度,因此我生成了 {SIZE 8 8 8} 类型的 PCD,它被读取为 Float64。而其他两个被读取为 Float32。
    • 我检查了您的代码,PCD 文件正在被正确读取和可视化。观察transformed_floattransformed_double 文件后,数值差别不大,只有几厘米左右的精度损失。如此小的差异在可视化中不会清晰可见,因此转换为双精度不会产生任何视觉差异。您的代码和 PCD 文件已正确显示。
    • 是的,差别很小。在raw_float 点云中,点是稀疏的。而在transformed_float中,点以线的形式分布。我根据我的视觉所见做出这些评论。对我来说,数据近似看起来是最合理的原因。现在,考虑一个我需要为本地化进行扫描匹配的用例。这种近似会导致任何差异吗?
    • 为什么transformed_double PCD 的情况下可视化有什么不同?我检查了 PCD 文件阅读器内部,并确认这些点被解析为 Float64。
    猜你喜欢
    • 2015-08-19
    • 2011-05-26
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    相关资源
    最近更新 更多