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. ReturnsGDKRes::kSuccesson success, and thepointcloudparameter 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)
};
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. ReturnsGDKRes::kSuccesson success, and thepointcloudparameter 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. ReturnsGDKRes::kSuccesson success, and thefpsparameter 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. ReturnsGDKRes::kSuccesson success, and thelatencyparameter 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. ReturnsGDKRes::kSuccesson 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¶
- GDK initialization:
agibot::gdk::GDKInit()must be called to initialize the GDK system before using the Lidar functionality - GDK release:
agibot::gdk::GDKRelease()must be called to release GDK system resources before the program ends - Initialization wait: After creating the Lidar object, it is recommended to wait 1 second to ensure the DDS connection is established
- Timeout setting: Set an appropriate timeout based on actual requirements to avoid long blocking
- Return value check: Check whether the GDKRes return value is kSuccess before use
- Smart pointer management: PointCloud objects are managed using shared_ptr; pay attention to their lifecycle
- Timestamp precision: The timestamp unit is nanoseconds, which can be used for precise time synchronization
- Point cloud processing: Point cloud data volumes are large; pay attention to memory usage when processing
- Lidar selection: Choose the appropriate lidar type (front/rear) based on the application scenario
- Data parsing: Point cloud data must be parsed correctly according to the fields information
- Coordinate system: Pay attention to the coordinate system definition of the point cloud data
- Resource release: Call
CloseLidar()to release resources once finished - Error handling: Always check the GDKRes return value to ensure the operation succeeded
- Unimplemented methods:
GetLidarFps()andGetLidarLatency()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