Skip to content

GDK Lidar Interface Documentation (C++)

Overview

The Lidar module provides G02 robots with the capability to acquire real-time point cloud data. Through the C++ interface, developers can conveniently obtain the robot's environmental perception data, suitable for SLAM mapping, obstacle detection, navigation and obstacle avoidance, environment modeling, and many other scenarios.

Interface Description

Lidar Class

This class encapsulates the main data acquisition interfaces of the lidar sensor.

1. GetLatestPointCloud()

  • Function: Get the latest point cloud data
  • Parameters:
Parameter Type Description
lidar_type const LidarType& Lidar type enum value
timeout_ms const float Timeout duration (milliseconds)
pointcloud std::shared_ptr<PointCloud>& Output parameter, pointer to the point cloud data
  • Return value: GDKRes, an operation result status code. Returns GDKRes::kSuccess on success, and the pointcloud parameter contains the point cloud data

PointCloud Object — Detailed Description

The PointCloud struct contains the following members:

Member Type Description Unit
timestamp_ns uint64_t Timestamp at which the point cloud data was captured Nanoseconds
width int Width of the point cloud (number of points) Points
height int Height of the point cloud (number of points) Points
point_step int Number of bytes occupied by each point Bytes
row_step int Number of bytes occupied by each row Bytes
is_bigendian bool Whether the data is big-endian Boolean
is_dense bool Whether this is a dense point cloud (no invalid points) Boolean
fields std::vector<PointField> List of field information, defining the attribute structure of each point in the point cloud None
data_view DataView Raw binary data view of the point cloud Data view

struct PointCloud {
 int width{0};   ///< point cloud width
 int height{0};  ///< point cloud height

 std::vector<PointField> fields{};  ///< point cloud fields
 int point_step{0};                 ///< point step
 int row_step{0};                   ///< row step
 bool is_bigendian{false};          ///< is bigendian
 bool is_dense{true};               ///< is dense

 DataView data_view{};      ///< point cloud data view
 uint64_t timestamp_ns{0};  ///< point cloud timestamp(ns)
};
fields (field information list):

Each field contains the following attributes:

Member Type Description
name std::string Field name (e.g. "x", "y", "z", "intensity")
offset uint32_t Offset within the point data
datatype uint8_t Data type
count uint32_t Number of elements in this field
struct PointField {
 std::string name{};   // point field name (x, y, z, intensity, etc.)
 uint32_t offset{0};   // point field offset
 uint8_t datatype{0};  // point field datatype
 uint32_t count{1};    // point field count
};

data_view (raw data):

  • Type: DataView
  • Description: Raw binary data view of the point cloud
  • Note: Must be parsed according to the fields information
class DataView {
public:
 /// @enum OwnershipType
 /// @brief ownership type
 /// @details ownership type related information
 enum class OwnershipType { OWNED, BORROWED };

 DataView() = default;

 DataView(const void* data, size_t size);

 explicit DataView(const std::vector<uint8_t>& vec);

 DataView(const DataView& other);

 DataView& operator=(const DataView& other);
 DataView(DataView&& other) noexcept;
 DataView& operator=(DataView&& other) noexcept;

 /// @brief data
 /// @details use to get the data of the data view
 /// @return the data of the data view
 const uint8_t* data() const { return data_; }

 /// @brief mutable_data
 /// @details use to get the mutable data of the data view
 /// @return the mutable data of the data view
 uint8_t* mutable_data() { return const_cast<uint8_t*>(data_); }

 /// @brief size
 /// @details use to get the size of the data view
 /// @return the size of the data view
 size_t size() const { return size_; }

 /// @brief IsOwned
 /// @details use to check if the data view is owned
 /// @return true if the data view is owned, false otherwise
 bool IsOwned() const { return ownership_ == OwnershipType::OWNED; }

 /// @brief Clone
 /// @details use to clone the data view
 /// @return the cloned data view
 DataView Clone() const;

 /// @brief CreateOwnedFrom
 /// @details use to create a data view from owned data
 /// @param data the data of the data view, input parameter
 /// @param size the size of the data view, input parameter
 /// @return the created data view
 static DataView CreateOwnedFrom(const void* data, size_t size);

 /// @brief AssignOwnedData
 /// @details use to assign owned data to the data view
 /// @param data the data of the data view, input parameter
 /// @param size the size of the data view, input parameter
 void AssignOwnedData(const void* data, size_t size);

private:
 const uint8_t* data_ = nullptr;
 size_t size_ = 0;
 OwnershipType ownership_ = OwnershipType::BORROWED;
 std::vector<uint8_t> owned_buffer_;
};

Lidar types: - LidarType::kLidarFront: Front lidar - LidarType::kLidarBack: Rear lidar

  • Example:
#include <iostream>
#include <chrono>
#include <thread>
#include <memory>
#include "gdk/gdk.h"

int main() {
    // Initialize the GDK system
    if (agibot::gdk::GDKInit() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK initialization failed" << std::endl;
        return -1;
    }
    std::cout << "GDK initialized successfully" << std::endl;

    agibot::gdk::Lidar lidar;

    // Available types: kLidarFront (front lidar), kLidarBack (rear lidar)
    agibot::gdk::LidarType lidar_type = agibot::gdk::LidarType::kLidarFront;
    std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established
    std::shared_ptr<agibot::gdk::PointCloud> pointcloud = std::make_shared<agibot::gdk::PointCloud>();
    lidar.GetLatestPointCloud(lidar_type, 500.0, pointcloud);

    if (pointcloud != nullptr) {
        std::cout << "✅ Timestamp: " << pointcloud->timestamp_ns << std::endl;
        std::cout << "Point cloud size: " << pointcloud->width << " x " << pointcloud->height << std::endl;
        std::cout << "Point step: " << pointcloud->point_step << std::endl;
        std::cout << "Row step: " << pointcloud->row_step << std::endl;
        std::cout << "Is big-endian: " << (pointcloud->is_bigendian ? "Yes" : "No") << std::endl;
        std::cout << "Is dense: " << (pointcloud->is_dense ? "Yes" : "No") << std::endl;

        // Print field information
        std::cout << "Number of fields: " << pointcloud->fields.size() << std::endl;
        for (size_t j = 0; j < pointcloud->fields.size(); ++j) {
            const auto& field = pointcloud->fields[j];
            std::cout << "  Field " << (j + 1) << ": " << field.name
                    << " (offset: " << field.offset
                    << ", type: " << field.datatype
                    << ", count: " << field.count << ")" << std::endl;
        }
    } else {
        std::cout << "No point cloud data received" << std::endl;
    }

    // Release GDK system resources
    if (agibot::gdk::GDKRelease() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK release failed" << std::endl;
        return -1;
    }
    std::cout << "GDK released successfully" << std::endl;

    return 0;
}

2. GetNearestPointCloud()

  • Function: Get the point cloud data nearest to a specified timestamp
  • Parameters:
Parameter Type Description
lidar_type const LidarType& Lidar type enum value
timestamp_ns const uint64_t Target timestamp (nanoseconds)
timeout_ms const float Timeout duration (milliseconds)
pointcloud std::shared_ptr<PointCloud>& Output parameter, pointer to the point cloud data
  • Return value: GDKRes, an operation result status code. Returns GDKRes::kSuccess on success, and the pointcloud parameter contains the point cloud data

  • Example:

#include <iostream>
#include <chrono>
#include <thread>
#include <memory>
#include "gdk/gdk.h"

int main() {
    // Initialize the GDK system
    if (agibot::gdk::GDKInit() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK initialization failed" << std::endl;
        return -1;
    }
    std::cout << "GDK initialized successfully" << std::endl;

    agibot::gdk::Lidar lidar;

    // Available types: kLidarFront (front lidar), kLidarBack (rear lidar)
    agibot::gdk::LidarType lidar_type = agibot::gdk::LidarType::kLidarFront;
    std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established
    std::shared_ptr<agibot::gdk::PointCloud> pointcloud = std::make_shared<agibot::gdk::PointCloud>();
    lidar.GetLatestPointCloud(lidar_type, 500.0, pointcloud);

    if (pointcloud != nullptr) {
        std::cout << "✅ Timestamp: " << pointcloud->timestamp_ns << std::endl;
        std::cout << "Point cloud size: " << pointcloud->width << " x " << pointcloud->height << std::endl;
        std::cout << "Point step: " << pointcloud->point_step << std::endl;
        std::cout << "Row step: " << pointcloud->row_step << std::endl;
        std::cout << "Is big-endian: " << (pointcloud->is_bigendian ? "Yes" : "No") << std::endl;
        std::cout << "Is dense: " << (pointcloud->is_dense ? "Yes" : "No") << std::endl;

        // Print field information
        std::cout << "Number of fields: " << pointcloud->fields.size() << std::endl;
        for (size_t j = 0; j < pointcloud->fields.size(); ++j) {
            const auto& field = pointcloud->fields[j];
            std::cout << "  Field " << (j + 1) << ": " << field.name
                    << " (offset: " << field.offset
                    << ", type: " << field.datatype
                    << ", count: " << field.count << ")" << std::endl;
        }

        // Look up the nearest point cloud data
        std::shared_ptr<agibot::gdk::PointCloud> pointcloud_nearest = std::make_shared<agibot::gdk::PointCloud>();
        agibot::gdk::GDKRes res = lidar.GetNearestPointCloud(
            lidar_type,
            pointcloud->timestamp_ns - 1000000000LL, // 1 second earlier
            1000.0,
            pointcloud_nearest
        );
        if (res == agibot::gdk::GDKRes::kSuccess && pointcloud_nearest != nullptr) {
            std::cout << "✅ Nearest point cloud data: " << pointcloud_nearest->timestamp_ns << std::endl;
            std::cout << "Point cloud size: " << pointcloud_nearest->width << " x " << pointcloud_nearest->height << std::endl;
        } else {
            std::cout << "❌ No nearest Front lidar data found" << std::endl;
        }
    } else {
        std::cout << "No point cloud data received" << std::endl;
    }

    // Release GDK system resources
    if (agibot::gdk::GDKRelease() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK release failed" << std::endl;
        return -1;
    }
    std::cout << "GDK released successfully" << std::endl;

    return 0;
}

3. GetLidarFps()

  • Function: Get the lidar data acquisition frame rate
  • Parameters:
Parameter Type Description
lidar_type const LidarType& Lidar type enum value
fps float& Output parameter, lidar frame rate (FPS)
  • Return value: GDKRes, an operation result status code. Returns GDKRes::kSuccess on success, and the fps parameter contains the frame rate value

  • Example:

#include <iostream>
#include <chrono>
#include <thread>
#include "gdk/gdk.h"

int main() {
    // Initialize the GDK system
    if (agibot::gdk::GDKInit() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK initialization failed" << std::endl;
        return -1;
    }
    std::cout << "GDK initialized successfully" << std::endl;

    agibot::gdk::Lidar lidar;
    std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established

    agibot::gdk::LidarType lidar_type = agibot::gdk::LidarType::kLidarFront;

    float fps;
    if (lidar.GetLidarFps(lidar_type, fps) != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "Failed to get lidar fps" << std::endl;
    } else {
        std::cout << "Lidar fps: " << fps << std::endl;
    }

    // Release GDK system resources
    if (agibot::gdk::GDKRelease() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK release failed" << std::endl;
        return -1;
    }
    std::cout << "GDK released successfully" << std::endl;

    return 0;
}

4. GetLidarLatency()

  • Note: Time synchronization must be performed before retrieving lidar data latency statistics, otherwise the latency statistics will be inaccurate
  • Function: Get lidar data latency statistics
  • Parameters:
Parameter Type Description
lidar_type const LidarType& Lidar type enum value
window_seconds const float Statistics window duration (seconds)
latency LatencyStats& Output parameter, latency statistics information
  • Return value: GDKRes, an operation result status code. Returns GDKRes::kSuccess on success, and the latency parameter contains the latency statistics information

  • LatencyStats struct description:

struct LatencyStats {
  double max_latency_ms{0.0};    ///< max latency(ms)
  double avg_latency_ms{0.0};    ///< average latency(ms)
  double p99_latency_ms{0.0};    ///< 99th percentile latency(ms)
  double p999_latency_ms{0.0};   ///< 99.9th percentile latency(ms)
  double p9999_latency_ms{0.0};  ///< 99.99th percentile latency(ms)
};
Member Type Description Unit
max_latency_ms double Maximum latency Milliseconds
avg_latency_ms double Average latency Milliseconds
p99_latency_ms double 99th percentile latency Milliseconds
p999_latency_ms double 99.9th percentile latency Milliseconds
p9999_latency_ms double 99.99th percentile latency Milliseconds
  • Example:
#include <iostream>
#include <chrono>
#include <thread>
#include "gdk/gdk.h"

int main() {
    // Initialize the GDK system
    if (agibot::gdk::GDKInit() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK initialization failed" << std::endl;
        return -1;
    }
    std::cout << "GDK initialized successfully" << std::endl;

    agibot::gdk::Lidar lidar;
    std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established

    agibot::gdk::LidarType lidar_type = agibot::gdk::LidarType::kLidarFront;

    agibot::gdk::LatencyStats latency;
    if (lidar.GetLidarLatency(lidar_type, 1.0, latency) != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "Failed to get lidar latency" << std::endl;
    } else {
        std::cout << "Lidar latency stats:" << std::endl;
        std::cout << "  Max latency: " << latency.max_latency_ms << "ms" << std::endl;
        std::cout << "  Average latency: " << latency.avg_latency_ms << "ms" << std::endl;
        std::cout << "  P99 latency: " << latency.p99_latency_ms << "ms" << std::endl;
        std::cout << "  P99.9 latency: " << latency.p999_latency_ms << "ms" << std::endl;
        std::cout << "  P99.99 latency: " << latency.p9999_latency_ms << "ms" << std::endl;
    }

    // Release GDK system resources
    if (agibot::gdk::GDKRelease() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK release failed" << std::endl;
        return -1;
    }
    std::cout << "GDK released successfully" << std::endl;

    return 0;
}

5. CloseLidar()

  • Function: Close the lidar DDS connection
  • Parameters: None
  • Return value: GDKRes, an operation result status code. Returns GDKRes::kSuccess on success

  • Example:

#include <iostream>
#include <chrono>
#include <thread>
#include "gdk/gdk.h"

int main() {
    // Initialize the GDK system
    if (agibot::gdk::GDKInit() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK initialization failed" << std::endl;
        return -1;
    }
    std::cout << "GDK initialized successfully" << std::endl;

    agibot::gdk::Lidar lidar;
    std::cout << "Lidar init" << std::endl;

    // Use the lidar...

    // Close the lidar
    if (lidar.CloseLidar() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "Failed to close lidar" << std::endl;
    } else {
        std::cout << "Lidar closed successfully" << std::endl;
    }

    // Release GDK system resources
    if (agibot::gdk::GDKRelease() != agibot::gdk::GDKRes::kSuccess) {
        std::cout << "GDK release failed" << std::endl;
        return -1;
    }
    std::cout << "GDK released successfully" << std::endl;

    return 0;
}

Usage Notes

  1. GDK initialization: agibot::gdk::GDKInit() must be called to initialize the GDK system before using the Lidar functionality
  2. GDK release: agibot::gdk::GDKRelease() must be called to release GDK system resources before the program ends
  3. Initialization wait: After creating the Lidar object, it is recommended to wait 1 second to ensure the DDS connection is established
  4. Timeout setting: Set an appropriate timeout based on actual requirements to avoid long blocking
  5. Return value check: Check whether the GDKRes return value is kSuccess before use
  6. Smart pointer management: PointCloud objects are managed using shared_ptr; pay attention to their lifecycle
  7. Timestamp precision: The timestamp unit is nanoseconds, which can be used for precise time synchronization
  8. Point cloud processing: Point cloud data volumes are large; pay attention to memory usage when processing
  9. Lidar selection: Choose the appropriate lidar type (front/rear) based on the application scenario
  10. Data parsing: Point cloud data must be parsed correctly according to the fields information
  11. Coordinate system: Pay attention to the coordinate system definition of the point cloud data
  12. Resource release: Call CloseLidar() to release resources once finished
  13. Error handling: Always check the GDKRes return value to ensure the operation succeeded
  14. Unimplemented methods: GetLidarFps() and GetLidarLatency() are currently not implemented; take note when using them

Application Scenarios

  • SLAM mapping: Use point cloud data for simultaneous localization and mapping
  • Obstacle detection: Real-time detection of obstacles in the environment
  • Navigation and obstacle avoidance: Provide environmental perception information for robot navigation
  • Environment modeling: Build 3D environment models
  • Object recognition: Combine point cloud data for object detection and recognition
  • Path planning: Plan safe paths based on point cloud data
  • Data fusion: Fuse with other sensor data to improve perception accuracy
  • 3D reconstruction: Use point cloud data for 3D scene reconstruction
  • Distance measurement: Precisely measure the distance to obstacles
  • Safety monitoring: Monitor the safety zone around the robot