Point Cloud Library with Velodyne LiDAR


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 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.


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


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.


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.


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


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.


// 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.


// 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;
    throw std::runtime_error( "This PointType is unsupported." );


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

    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.

24 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.

    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.

    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.

    1. Hi Ibrahim Shaikh,

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

      set(CMAKE_CXX_STANDARD 11)

      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.

  6. Hi Tsukasa Sugiura,
    I successfully retrieved Velodyne Lidar data from PCAP file . But I want to ask you how can I get the Inertia Measurement Units(IMU) form point cloud data.

    1. Hi Schofield,

      pcl::HDLGrabber/pcl::VLPGrabber doesn’t have the features to retrieve data from IMU.
      If you want to use IMU data, You need to implement that features yourself.

  7. Hello! Thank you for this very thoughtful and thorough tutorial.

    I am trying to use data from a VLP-16 in a ROS framework. The PCL version that I’m using, however, is 1.7.2. I am hesitant to try and update, as I fear this might cause problems with ROS later.

    Is there a way that I can format the data such that I can load it into a pointcloud and view it? Some transfer of my pcl file to an intermediate file type, maybe?

    Again, thank you so much for working hard and creating this tutorial!

  8. Hello Tsukasa,
    First of all, I would like to appreciate you for the nice post. Really it helped me lot read pcap data from file. Now am able to render the pcap file in pcl visualizer. But there is some issue with coordinate conversion. Points are rendering in curvely fashin instead of straingt line. I tried to attach screen shots , but couldnt succeeded. Currently i am using following code snippet to convert laser raw measurements to 3D coordinates. Will you please suggest me possible solutions to fix this issue.

    for( const velodyne::Laser& laser : lasers ){
        const double distance = static_cast<float>(laser.distance);
        const double azimuth = laser.azimuth  * CV_PI / 180.0;
        const double vertical = laser.vertical * CV_PI / 180.0;
        float x = static_cast<float>((distance * std::cos(vertical)) * std::sin(azimuth));
        float y = static_cast<float>((distance * std::cos(vertical)) * std::cos(azimuth));
        float z = static_cast<float>((distance * std::sin(vertical)));
        if (x == 0.0f && y == 0.0f && z == 0.0f) {
            x = std::numeric_limits::quiet_NaN();
            y = std::numeric_limits::quiet_NaN();
            z = std::numeric_limits::quiet_NaN();
        pcl::PointXYZRGB basic_point;
        basic_point.x = x;
        basic_point.y = y;
        basic_point.z = z;
    1. Hi Ajay,

      In this article using Velodyne grabber that has implemented in PCL.
      It returns coordinated Point Cloud data. You don’t need to convert coordinates yourself.

  9. Hi,Tsukasa Sugiura. Thanks for your code.
    I build my project on Windows and in QT with no error and waring. But when I run the project, it crashed when I wired my VLP16 and began to show the point cloud.
    Should I set something before I run the project?
    Thanks for your help.

    1. Hi Yuhang Feng,

      Can you run this tutorial?
      Please confirm that you can use PCL with Qt GUI.

      Also, Can you run PCL with VLP-16?
      Please confirm that you can use VLP-16 without Qt GUI.

  10. Hi Tsukasa Sugiura,

    I run this program and giving pcapfile ,and just get a black background window, it seems i get the seem situation with Ibrahim Shaikh.
    and when i debug the program, i find the cloud is NULL in main.cpp#L103-L108,

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

    so it can’t addpointcloud to the viewer ,can you give me some suggest?

    1. Hi Lulu liu,

      I don’t know why cloud pointer indicates NULL in your environment.
      If you want to retrieve data from PCAP, You need to build PCL from source code yourself.
      Also, pcl::VLPGrabber has not implemented the RGB color handler yet. (It will be implemented in PCL 1.9.0.)
      Please use pcl::PointXYZ or pcl::PointXYZI instead of pcl::PointXYZRGBA.

      If you want more information, Please post to users forum.

  11. Tsukasa Sugiura,
    Thank you for writing this framework. It has been immensely helpful.

    Currently, I am reading data from a .pcd file and sorting it into a k-d tree. I then stream data from a vlp-16 sensor. I need to compare my data stream to my k-d tree and am struggling with passing the k-d tree into the callback function. Do you have any suggestions for how to pass the k-d tree into the callback function or how to bring the k-d tree into scope? Thank you for all the help you’ve given already!

    With gratitude,

Leave a Reply

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