基于PCL抓取Velodyne激光雷达数据包可视化

Velodyne 高清激光雷达 (HDL) 采集器

Velodyne HDL 是一种基于网络的 3D LiDAR 系统,每秒生成包含超过 700,000 个点的 360 度点云。

PCL 中提供的 HDL Grabber 模仿其他 Grabbers,使其几乎可以即插即用。 然而,由于 HDL 设备是基于网络的,因此在某些平台上存在一些问题。

HDL Grabber 支持原始的 HDL-64e 以及 HDL-32e。 有关这些传感器的更多信息,请访问 Velodyne 网站Velodyne’s Web Site

基本网络设置

Velodyne HDL 使用网络数据包为设备中的每个激光器提供范围和强度数据。 HDL-64e 由 64 个激光器组成,而 HDL-32e 由 32 个激光器组成。

默认情况下,HDL-64e 和 HDL-32e 在 192.168.3 子网上生成 UDP 网络数据包。 从 HDL-32e(固件版本 2)开始,用户可以自定义此网络子网。

HDL 可以直接连接到您的计算机,也可以连接到网络交换机(包括带有内置无线接入点的网络交换机)。 无论如何,您的计算机的一个网络接口卡 (NIC) [无论是有线 RJ-45 连接还是无线连接] 都需要配置为在此 192.168.3 子网上。 请查阅您的操作系统文档以了解如何执行此操作。

除了 NIC 设置之外,您可能还需要更改操作系统的防火墙规则。 HDL 在端口 2368(默认情况下)上生成数据包。 固件版本 2 的 HDL-32e 可以设置为使用不同的端口。 请查阅您的防火墙文档以在您的防火墙中打开此端口。

最后,现代 Linux 内核具有超越基本防火墙规则的高级网络攻击防护。 HDL-32e 生成的 UDP 数据包可能会被操作系统使用这些攻击防护之一过滤。 您需要为相应的 NIC 禁用 rp_filter 防护。 有关如何禁用此过滤器的更多信息,请参阅下面标题为禁用反向路径过滤器的部分Disabling Reverse Path Filter

PCAP文件 

Wireshark是一种流行的网络数据包分析程序,适用于大多数平台,包括 Linux、MacOS 和 Windows。 该工具使用称为 PCAP的事实上的标准网络数据包捕获文件格式。 许多公开可用的 Velodyne HDL 数据包捕获使用此 PCAP 文件格式作为记录和回放的方式。 如果 PCL 编译时支持 PCAP,则这些 PCAP 文件可与 HDL Grabber 一起使用。

Velodyne 在其网站website上提供示例 PCAP 文件

编译支持 PCAP 的 HDL Grabber

在 Linux 上,这涉及安装 libpcap-dev (Ubuntu) 或 libpcap-devel (Fedora)。 CMake 应该找到 pcap 库,并自动配置 PCL 来使用它们。

在 Windows 上,这涉及安装 WinPCAP installer 和 WinPCAP developer’s pack。 您还需要将环境变量 PCAPDIR 设置为解压缩开发人员包的目录。 完成后,您应该能够再次运行 CMake,它应该会找到相应的文件。

注意 - 您不需要编译支持 PCAP 的 HDL Grabber。 仅当您将通过抓取器重放 PCAP 文件时才需要。

示例程序

SimpleHDLViewer.h


#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/hdl_grabber.h>
#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>

using namespace std::chrono_literals;
using namespace pcl::console;
using namespace pcl::visualization;

class SimpleHDLViewer
{
    typedef pcl::PointCloud<pcl::PointXYZI> Cloud;
    typedef Cloud::ConstPtr CloudConstPtr;

public:

    SimpleHDLViewer(pcl::Grabber &grabber, PointCloudColorHandler<pcl::PointXYZI> &handler);

    void cloud_callback(const CloudConstPtr& cloud);

    void run();

private:

    PCLVisualizer::Ptr cloud_viewer_;

    pcl::Grabber &grabber_;
    std::mutex cloud_mutex_;

    CloudConstPtr cloud_;
    PointCloudColorHandler<pcl::PointXYZI> &handler_;
};

SimpleHDLViewer.cpp

#include "SimpleHDLViewer.h"

SimpleHDLViewer::SimpleHDLViewer(pcl::Grabber &grabber,
                  PointCloudColorHandler<pcl::PointXYZI> &handler) :
                  cloud_viewer_(new PCLVisualizer("PCL HDL Cloud")),
                  grabber_(grabber),
                  handler_(handler)
{
}

void SimpleHDLViewer::cloud_callback(const CloudConstPtr &cloud)
{
    std::lock_guard<std::mutex> lock(cloud_mutex_);
    cloud_ = cloud;
}

void SimpleHDLViewer::run()
{
    cloud_viewer_->addCoordinateSystem(3.0);
    cloud_viewer_->setBackgroundColor(0, 0, 0);
    cloud_viewer_->initCameraParameters();
    cloud_viewer_->setCameraPosition(0.0, 0.0, 30.0, 0.0, 1.0, 0.0, 0);
    cloud_viewer_->setCameraClipDistances(0.0, 50.0);

    std::function<void (const CloudConstPtr&)> cloud_cb =
        [this] (const CloudConstPtr &cloud) {cloud_callback(cloud);};
    boost::signals2::connection cloud_connection = grabber_.registerCallback(cloud_cb);

    grabber_.start();
    
    while (!cloud_viewer_->wasStopped())
    {
        CloudConstPtr cloud;

        // See if we can get a cloud
        if (cloud_mutex_.try_lock())
        {
            cloud_.swap(cloud);
            cloud_mutex_.unlock();
        }

        if (cloud)
        {
            handler_.setInputCloud(cloud);
            if (!cloud_viewer_->updatePointCloud(cloud, handler_, "HDL"))
                cloud_viewer_->addPointCloud(cloud, handler_, "HDL");

            cloud_viewer_->spinOnce();
        }

        if (!grabber_.isRunning())
            cloud_viewer_->spin();

        std::this_thread::sleep_for(100us);
    }

    grabber_.stop();

    cloud_connection.disconnect();
}

hdl_viewer_simple.cpp


#include "SimpleHDLViewer.h"
#include <pcl/io/vlp_grabber.h>


int main(int argc, char ** argv)
{
  std::string hdlCalibration, pcapFile;

  parse_argument(argc, argv, "-calibrationFile", hdlCalibration);
  parse_argument(argc, argv, "-pcapFile", pcapFile);

  // pcapFile = "HDL32-V2_Monterey Highway.pcap";
  pcl::HDLGrabber grabber(hdlCalibration, pcapFile);
  // pcl::VLPGrabber g(pcapFile);
  PointCloudColorHandlerGenericField<pcl::PointXYZI> color_handler("intensity");

  SimpleHDLViewer v(grabber, color_handler);
  v.run();
  return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
 
project(pcl_hdl_viewer_simple)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG -O0 -Wall -g2 -ggdb")
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

find_package(PCL 1.10 REQUIRED COMPONENTS)
 
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
#LINK_LIBRARIES(${PCL_LIBRARIES})

aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} CPP_SOURCE)
#add_executable(pcl_hdl_viewer_simple hdl_viewer_simple.cpp)
add_executable(pcl_hdl_viewer_simple ${CPP_SOURCE})

target_link_libraries(pcl_hdl_viewer_simple ${PCL_LIBRARIES} pthread)

build.sh

#!/bin/bash

CURRENT_DIR=$(cd $(dirname $0); pwd)
FILE=${CURRENT_DIR}/build

if [ ! -d "$FILE" ]; then
    echo "$FILE not exist"
    mkdir ${FILE}
fi

cd build

cmake ..

make

直接运行build.sh编译

猜你喜欢

转载自blog.csdn.net/qq_35097289/article/details/130263506