Point Cloud Library with Velodyne LiDAR

Introduction

I tried Velodyne VLP-16 at Fujiyoshi Lab. of Chubu University.
Thank you so much for giving me this opportunity.

Velodyne LiDAR

What is LiDAR?

The LiDAR is sensor to retrieve three-dimensional distance and reflectance intensity of horizontal 360 degree that uses rotates laser range units.
Velodyne‘s LiDAR is mounted on a robot car (autonomous car) and drones, that have been utilized to sense the surrounding environment.


VLP-16

VLP-16 retrieve data by skipping an infrared laser of vertical range +/- 15 degree.
In horizontal, It retrieve data with resolution of 0.1~0.4 degree at 300~1200rpm.
HDL-64E/HDL-32E have high resolution of vertical direction than VLP-16, because threse sensors have more lasers in vertical direction.

vlp16
vlp16_laser

Data in the UDP/IP will be sent from the LiDAR.
The receive side will retrieve data with analyzes packets.

VeloView

VeloView is viewer application for Velodyne LiDARs.
This viewer can viewing data that retrieve from LiDAR in real time, recording data and saving data to file (PCAP, CSV).
The PCAP file includes all received packet data.
The CSV file includes one frame data that is reflection intensity and distance of 0-359.9 degree.

PCL with Velodyne LiDAR

Point Cloud Library (PCL) have Grabber for input data from Velodyne LiDARs.
You can easily retrieve Point Cloud from Velodyne LiDARs same as other Grabbers.

Also, You can choose whether to retrieve data from sensor or PCAP file by argument to constructor of Grabber.
However, If you want to retrieve data from PCAP file, You need build PCL with WITH_PCAP option. (Pre-built library is disabled this option.)

  • HDLGrabber
  • This Grabber for HDL-64E/HDL-32E.

  • VLPGrabber
  • This Grabber for VLP-16.

Drawing Point Cloud retrieve from Velodyne LiDAR

This sample program is published in following.

Include

You need to include pcl/io/vlp_grabber.h in order to use pcl::VLPGrabber.
If you want to use pcl::HDLGrabber, You need to include pcl/io/hdl_grabber.h.

main.cpp#L7

#include <pcl/io/vlp_grabber.h>
//#include <pcl/io/hdl_grabber.h>

Grabber

You will create instance of pcl::VLPGrabber.
At this time, You can choose whether to retrieve data from sensor or PCAP file by argument to constructor of Grabber.
If you want to retrieve data from PCAP file, You will specify path to PCAP file to constructor.
If you want to retrieve real-time data from sensor, You will specify IP address and port number to constructor.


*1 If you want to use pcl::HDLGrabber and HDL-64, You need specify calibration file to constructor.
*2 IP address and port number is depends on Velodyne LiDAR and NIC settings.

main.cpp#L82-L90

// VLP Grabber
boost::shared_ptr<pcl::VLPGrabber> grabber;
if( !pcap.empty() ){
    std::cout << "Capture from PCAP..." << std::endl;
    grabber = boost::shared_ptr<pcl::VLPGrabber>( new pcl::VLPGrabber( pcap ) );
}
else if( !ipaddress.empty() && !port.empty() ){
    std::cout << "Capture from Sensor..." << std::endl;
    grabber = boost::shared_ptr<pcl::VLPGrabber>( new pcl::VLPGrabber( boost::asio::ip::address::from_string( ipaddress ), boost::lexical_cast<unsigned short>( port ) ) );
}

Color Handler

The data retrieved from Velodyne LiDARs has not color information.
For this reason, You need to specify rules for displayed on viewer.
You will create pcl::visualization::PointCloudColorHandler each pcl::PointType.
pcl::visualization::PointCloudColorHandler that was created is give to viewer.

main.cpp#L51-L68

// Point Cloud Color Hndler
pcl::visualization::PointCloudColorHandler<PointType>::Ptr handler;
const std::type_info& type = typeid( PointType );
if( type == typeid( pcl::PointXYZ ) ){
    std::vector<double> color = { 255.0, 255.0, 255.0 };
    boost::shared_ptr<pcl::visualization::PointCloudColorHandlerCustom<PointType>> color_handler( new pcl::visualization::PointCloudColorHandlerCustom<PointType>( color[0], color[1], color[2] ) );
    handler = color_handler;
}
else if( type == typeid( pcl::PointXYZI ) ){
    boost::shared_ptr<pcl::visualization::PointCloudColorHandlerGenericField<PointType>> color_handler( new pcl::visualization::PointCloudColorHandlerGenericField<PointType>( "intensity" ) );
    handler = color_handler;
}
else if( type == typeid( pcl::PointXYZRGBA ) ){
    boost::shared_ptr<pcl::visualization::PointCloudColorHandlerRGBField<PointType>> color_handler( new pcl::visualization::PointCloudColorHandlerRGBField<PointType>() );
    handler = color_handler;
}
else{
    throw std::runtime_error( "This PointType is unsupported." );
}

main.cpp#L98-L110

while( !viewer->wasStopped() ){
    // Update Viewer
    viewer->spinOnce();

    boost::mutex::scoped_try_lock lock( mutex );
    if( lock.owns_lock() && cloud ){
        // Update Point Cloud
        handler->setInputCloud( cloud );
        if( !viewer->updatePointCloud( cloud, *handler, "cloud" ) ){
            viewer->addPointCloud( cloud, *handler, "cloud" );
        }
    }
}

Execution Result

It will be display Point Cloud that retrieved from Velodyne LiDAR when running this sample program.
This sample data (2014-11-10-11-32-17_Velodyne-VLP_10Hz_Monterey Highway.pcap) has been retrieved from sensor that mount on car top.
Point Cloud is attached color by reflected intensity of infrared laser.
You can see ambient environment such as street trees, buildings, road, and other cars.


11 thoughts on “Point Cloud Library with Velodyne LiDAR”

  1. Can you please provide instructions on how to compile with PCAP to play back lidar data. I am having trouble playing back the Monterey Highway data using the above code.
    Thanks

    1. Hi Raks,

      If you want to retrieve data from PCAP, You need build PCL that enabled WITH_PCAP option from source code yourself.

      You need to download WinPCAP Developer’s Pack.
      Please unzip and place it under an arbitrary directory. (e.g. C:\Program Files\WpdPack)
      And, Set WpdPack path to environment variable “PCAPDIR”.

      Then, You need to build PCL according to this build notes.
      At the step of configuring PCL with CMake, Please check WITH_PCAP.
      Please fill in the PCAP path.

      • PCAP
        • PCAP_INCLUDE_DIRS C:\Program Files\WpdPack\Include
        • PCAP_LIBRARIES C:\Program Files\WpdPack\Lib\x64\wpcap.lib (or C:\Program Files\WpdPack\Lib\wpcap.lib)
      • WITH
        • WITH_PCAP (check)
  2. I am using the vlpGrabber class to read pcap files and store the scans in a .pcd. But in the documentation the vlpgrabber has no member variable to return the current scan pointcloud. There is a variable current_sweep_xyzi, but it is a protected variable.

    How can I get the scan data? I appreciate any help you can provide.
    Thanks

    1. Hi Raks,

      In general, The grabber of PCL retrieve pcl::PointCloud data using callback function that registered by pcl::Grabber::registerCallback().
      All grabbers has this mechanism because they has inherited pcl::Grabber.
      You need learn how to retrieve pcl::PointCloud data using callback function.

  3. It works perfectly on Linux and PCL, but I want to identify keypoints and show them in the viwer.
    I’m trying to do it but I don’t know exactly when the var: “cloud” is filled with the points from the pcap file

    this is the code I want to add:

    #include <pcl/point_types.h>
    #include <pcl/features/normal_3d.h>
    
    {
      pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
    
      ... read, pass in or create a point cloud ...
    
      // Create the normal estimation class, and pass the input dataset to it
      pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
      ne.setInputCloud (cloud);
    
      // Create an empty kdtree representation, and pass it to the normal estimation object.
      // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
      pcl::search::KdTree::Ptr tree (new pcl::search::KdTree ());
      ne.setSearchMethod (tree);
    
      // Output datasets
      pcl::PointCloud::Ptr cloud_normals (new pcl::PointCloud);
    
      // Use all neighbors in a sphere of radius 3cm
      ne.setRadiusSearch (0.03);
    
      // Compute the features
      ne.compute (*cloud_normals);
    
      // cloud_normals->points.size () should have the same size as the input cloud->points.size ()
    }
    
    1. Hi Victor,

      The function that registered by pcl::Grabber::registerCallback() will be called once when grabber retrieved point cloud data.
      In the case of this sample program, It is a function object defined using lambda expression in main.cpp#L72-L79.
      You can write some processing to the new point cloud data that retrieved from grabber in here.
      (But, I don’t know whether your source code is correct.)

      If you want more information, I recommend you post to users forum.

  4. Helo there, I am using VLP-16 pcap files and the algorithm works perfecly, but I want to identify key points in the cloud, so I want to know where do you fill this pcl::PointCloud::ConstPtr cloud; cause my algorithm works with a given XYZ point cloud

  5. Hi Tsukasa Sugiura
    I am trying this VLP_grabber program in Ubuntu 14.04. I have successfully compiled the PCL in Ubuntu 14.04. But I am getting an error as below.

    user@user-BLRMIESPC-756:~/pcl/vlp_grabber/build$ make
    Scanning dependencies of target project
    [100%] Building CXX object CMakeFiles/project.dir/main.cpp.o
    /home/user/pcl/vlp_grabber/main.cpp: In function ‘int main(int, char<strong>)’:
    /home/user/pcl/vlp_grabber/main.cpp:90:9: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]
             };
             ^
    /home/user/pcl/vlp_grabber/main.cpp:90:9: error: conversion from ‘main(int, char</strong>)::__lambda0’ to non-scalar type ‘boost::function&lt;void(const boost::shared_ptr&lt;const pcl::PointCloud &gt;&amp;)&gt;’ requested
    make[2]: *** [CMakeFiles/project.dir/main.cpp.o] Error 1
    make[1]: *** [CMakeFiles/project.dir/all] Error 2
    make: *** [all] Error 2
    

    The code which I copied from Internet is giving error in following line number 90.

    boost::mutex mutex;
    boost::function<void( const pcl::PointCloud::ConstPtr& )> function = [ &cloud, &mutex ]( const pcl::PointCloud::ConstPtr& ptr ){
        boost::mutex::scoped_lock lock( mutex );
    
        // Point Cloud Processing
    
        cloud = ptr;
    }; 
    

    Kindly check the error and provide me a good solution.
    Thanks

    1. Hi Ibrahim Shaikh,

      I don’t know the cause of this error.
      Please add the following to CMakeLists.

      set(CMAKE_CXX_STANDARD 11)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      set(CMAKE_CXX_EXTENSIONS OFF)
      

      Sorry, I’m not familiar about Linux and GCC.
      I recommend that you post to PCL Users forum.

    2. Hi Tsukasa Sugiura,

      Thanks for your help and its working whatever you told me to do. But now when I am running the program and giving *.pcap file, one window is getting opened and its showing black background with 3 axis x,y,z in RGB color. This exactly mean I am not able to see point cloud from *.pcap file.
      Can you suggest something.

      Thank you

    3. Hi Ibrahim Shaikh,

      pcl::VLPGrabber has not implemented the RGB color handler yet.
      Please use pcl::PointXYZ or pcl::PointXYZI instead of pcl::PointXYZRGBA.

      That feature will be implemented in PCL 1.9.0 (PR#1738).
      If you want to use it, Please apply this change and build PCL from source code yourself.

Leave a Reply

Your email address will not be published. Required fields are marked *