GDK PNC Interface Documentation (C++)¶
Overview¶
The PNC (Planning and Control) module provides path planning and navigation control capabilities for the G02 robot. Through the C++ interface, developers can conveniently implement autonomous navigation, path planning, task state management, and other functions for the robot, suitable for various scenarios such as autonomous navigation, path planning, and task scheduling.
Interface Description¶
Pnc Class¶
This class encapsulates the main interfaces for robot path planning and navigation control.
1. GetTaskState()¶
- Function: Get the current task state
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
task_state |
PNCTaskState& |
Output parameter, task state information object |
- Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success; thetask_stateparameter contains the task state information
Detailed Description of the PNCTaskState Object¶
The PNCTaskState struct contains the following members:
| Member Name | Type | Description | Unit |
|---|---|---|---|
id |
uint32_t |
Task ID | No unit |
state |
uint32_t |
Task state code | No unit |
type |
uint32_t |
Task type | No unit |
message |
std::string |
State description message | String |
Task state code description:
- 0: Idle
- 1: Starting
- 2: Running
- 3: Pausing
- 4: Paused
- 5: Resuming
- 6: Cancelling
- 7: Cancelled
- 8: Failed
- 9: Succeeded
Task type description:
- 0: Idle
- 1: Normal navigation
- 2: Remote control
- Example:
#include "gdk/gdk.h"
#include <iostream>
#include <chrono>
#include <thread>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established
PNCTaskState task_state;
GDKRes result = pnc.GetTaskState(task_state);
if (result == GDKRes::kSuccess) {
std::cout << "PNC task state: " << task_state.state << std::endl;
std::cout << "PNC task ID: " << task_state.id << std::endl;
std::cout << "PNC task message: " << task_state.message << std::endl;
std::cout << "PNC task type: " << task_state.type << std::endl;
} else {
std::cout << "Failed to get task state" << std::endl;
}
return 0;
}
2. NormalNavi()¶
- Function: Execute normal navigation to the specified target point. Relocalization must be performed on the G02 Pad before execution
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
navi_req |
const NaviReq& |
Navigation request object |
- Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success
Detailed Description of the NaviReq Object¶
The NaviReq struct contains the following members:
| Member Name | Type | Description | Unit |
|---|---|---|---|
target |
Pose |
Target pose | Pose |
timestamp_ns |
uint64_t |
Navigation timestamp | Nanoseconds |
Pose struct:
| Member Name | Type | Description |
|---|---|---|
position |
Position |
Position information |
orientation |
Orientation |
Orientation information |
Position struct:
| Member Name | Type | Description | Unit |
|---|---|---|---|
x |
double |
Target position X coordinate | Meters |
y |
double |
Target position Y coordinate | Meters |
z |
double |
Target position Z coordinate | Meters |
Orientation struct:
| Member Name | Type | Description | Unit |
|---|---|---|---|
x |
double |
Target orientation quaternion X component | No unit |
y |
double |
Target orientation quaternion Y component | No unit |
z |
double |
Target orientation quaternion Z component | No unit |
w |
double |
Target orientation quaternion W component | No unit |
- Example:
#include "gdk/gdk.h"
#include <iostream>
#include <chrono>
#include <thread>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1 second to ensure the DDS connection is established
NaviReq navi_req;
navi_req.target.position.x = 2.0; // Target X coordinate
navi_req.target.position.y = 3.0; // Target Y coordinate
navi_req.target.position.z = 0.0; // Target Z coordinate
navi_req.target.orientation.x = 0.0; // Target orientation quaternion X
navi_req.target.orientation.y = 0.0; // Target orientation quaternion Y
navi_req.target.orientation.z = 0.0; // Target orientation quaternion Z
navi_req.target.orientation.w = 1.0; // Target orientation quaternion W
navi_req.timestamp_ns = 0; // Timestamp
GDKRes result = pnc.NormalNavi(navi_req);
if (result == GDKRes::kSuccess) {
std::cout << "Normal navigation started successfully" << std::endl;
} else {
std::cout << "Failed to start normal navigation" << std::endl;
}
return 0;
}
3. HighPrecisionNavi()¶
- Function: Execute high-precision navigation to the specified target point. Relocalization must be performed on the G02 Pad before execution
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
navi_req |
const NaviReq& |
Navigation request object |
-
Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success -
Example:
#include "gdk/gdk.h"
#include <iostream>
using namespace agibot::gdk;
int main() {
Pnc pnc;
NaviReq navi_req;
navi_req.target.position.x = 1.5; // Target X coordinate
navi_req.target.position.y = 2.5; // Target Y coordinate
navi_req.target.position.z = 0.0; // Target Z coordinate
navi_req.target.orientation.x = 0.0; // Target orientation quaternion X
navi_req.target.orientation.y = 0.0; // Target orientation quaternion Y
navi_req.target.orientation.z = 0.0; // Target orientation quaternion Z
navi_req.target.orientation.w = 1.0; // Target orientation quaternion W
navi_req.timestamp_ns = 0; // Timestamp
GDKRes result = pnc.HighPrecisionNavi(navi_req);
if (result == GDKRes::kSuccess) {
std::cout << "High-precision navigation started successfully" << std::endl;
} else {
std::cout << "Failed to start high-precision navigation" << std::endl;
}
return 0;
}
4. RelativeMove()¶
- Function: Execute a small-range translation. Simple obstacle stopping only, no obstacle avoidance. Relocalization must be performed on the G02 Pad before execution
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
navi_req |
const NaviReq& |
Navigation request object |
-
Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success -
Example:
#include "gdk/gdk.h"
#include <iostream>
using namespace agibot::gdk;
int main() {
Pnc pnc;
NaviReq navi_req;
navi_req.target.position.x = 0.5; // Relative X movement distance
navi_req.target.position.y = 0.0; // Relative Y movement distance
navi_req.target.position.z = 0.0; // Relative Z movement distance
navi_req.target.orientation.x = 0.0; // Relative rotation X
navi_req.target.orientation.y = 0.0; // Relative rotation Y
navi_req.target.orientation.z = 0.0; // Relative rotation Z
navi_req.target.orientation.w = 1.0; // Relative rotation W
navi_req.timestamp_ns = 0; // Timestamp
GDKRes result = pnc.RelativeMove(navi_req);
if (result == GDKRes::kSuccess) {
std::cout << "Relative move started successfully" << std::endl;
} else {
std::cout << "Failed to start relative move" << std::endl;
}
return 0;
}
5. CancelTask()¶
- Function: Cancel the navigation task with the specified ID
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
task_id |
uint32_t |
ID of the task to cancel |
-
Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success -
Example:
#include "gdk/gdk.h"
#include <iostream>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1));
// First get the current task state to obtain the task ID
PNCTaskState task_state;
if (pnc.GetTaskState(task_state) == GDKRes::kSuccess) {
uint32_t task_id = task_state.id;
GDKRes result = pnc.CancelTask(task_id);
if (result == GDKRes::kSuccess) {
std::cout << "Task cancelled successfully" << std::endl;
} else {
std::cout << "Failed to cancel task" << std::endl;
}
}
return 0;
}
6. PauseTask()¶
- Function: Pause the navigation task with the specified ID
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
task_id |
uint32_t |
ID of the task to pause |
-
Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success -
Example:
#include "gdk/gdk.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1));
// First get the current task state to obtain the task ID
PNCTaskState task_state;
if (pnc.GetTaskState(task_state) == GDKRes::kSuccess) {
uint32_t task_id = task_state.id;
GDKRes result = pnc.PauseTask(task_id);
if (result == GDKRes::kSuccess) {
std::cout << "Task paused successfully" << std::endl;
} else {
std::cout << "Failed to pause task" << std::endl;
}
}
return 0;
}
7. ResumeTask()¶
- Function: Resume the navigation task with the specified ID
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
task_id |
uint32_t |
ID of the task to resume |
-
Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success -
Example:
#include "gdk/gdk.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1));
// First get the current task state to obtain the task ID
PNCTaskState task_state;
if (pnc.GetTaskState(task_state) == GDKRes::kSuccess) {
uint32_t task_id = task_state.id;
GDKRes result = pnc.ResumeTask(task_id);
if (result == GDKRes::kSuccess) {
std::cout << "Task resumed successfully" << std::endl;
} else {
std::cout << "Failed to resume task" << std::endl;
}
}
return 0;
}
8. RequestChassisControl()¶
- Function: Request chassis control permission, used for remote control mode
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
control_mode |
int32_t |
Control request: 0 |
- Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success
Control mode description:
- Ackermann mode: Suitable for the kinematic model of a front-wheel-steered vehicle, controlled via linear velocity (linear.x) and angular velocity (angular.z)
- Crab mode: Supports omnidirectional movement, controlling forward/backward and left/right movement via linear.x and linear.y respectively
- Example:
#include "gdk/gdk.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1));
// Request remote control
GDKRes res = pnc.RequestChassisControl(0);
if (res == GDKRes::kSuccess) {
std::cout << "Remote control request succeeded" << std::endl;
} else {
std::cout << "Control request failed" << std::endl;
return 1;
}
// Wait for control permission to take effect
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// Now MoveChassis() can be used to control the chassis
Twist twist;
twist.linear.x = 0.3;
twist.angular.z = 0.0;
pnc.MoveChassis(twist);
return 0;
}
9. MoveChassis()¶
- Function: Move the chassis, used for chassis motion control in remote control mode
- Parameters:
| Parameter Name | Type | Description |
|---|---|---|
twist |
const Twist& |
Velocity command object, containing linear velocity and angular velocity |
- Return Value:
GDKRes, operation result status code. ReturnsGDKRes::kSuccesson success
Detailed Description of the Twist Object¶
The Twist struct contains the following members:
| Member Name | Type | Description | Unit |
|---|---|---|---|
linear |
Vector3 |
Linear velocity vector | Meters/second (m/s) |
angular |
Vector3 |
Angular velocity vector | Radians/second (rad/s) |
Vector3 struct:
| Member Name | Type | Description | Unit |
|---|---|---|---|
x |
double |
X-axis component | Depends on context |
y |
double |
Y-axis component | Depends on context |
z |
double |
Z-axis component | Depends on context |
Usage notes:
- Before calling MoveChassis(), you must first call RequestChassisControl() to request chassis control permission
- linear.x: Forward/backward speed (positive value for forward, negative value for backward)
- linear.y: Left/right translation speed (used in crab mode; positive value for left, negative value for right)
- linear.z: Usually 0
- angular.z: Angular velocity of rotation about the Z axis (positive value for counterclockwise, negative value for clockwise)
- Example:
#include "gdk/gdk.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace agibot::gdk;
int main() {
Pnc pnc;
std::this_thread::sleep_for(std::chrono::seconds(1));
// Request chassis control permission
GDKRes res = pnc.RequestChassisControl(0);
if (res != GDKRes::kSuccess) {
std::cout << "Failed to request chassis control" << std::endl;
return 1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// Ackermann mode: move forward and turn right
Twist twist;
twist.linear.x = 0.5; // Forward speed 0.5 m/s
twist.linear.y = 0.0;
twist.linear.z = 0.0;
twist.angular.x = 0.0;
twist.angular.y = 0.0;
twist.angular.z = -0.3; // Right turn angular velocity 0.3 rad/s
res = pnc.MoveChassis(twist);
if (res == GDKRes::kSuccess) {
std::cout << "Chassis movement command sent successfully" << std::endl;
}
// Stop after running for a while
std::this_thread::sleep_for(std::chrono::seconds(2));
res = pnc.get_task_state(task_state);
if (res == GDKRes::kSuccess) {
std::cout << "Task state: " << task_state.state << std::endl;
} else {
std::cout << "Failed to get task state" << std::endl;
}
auto task_id = task_state.id;
res = pnc.CancelTask(task_id);
if (res != GDKRes::kSuccess) {
std::cout << "Failed to cancel task" << std::endl;
}
// Crab mode: translate left
Twist twist;
twist.linear.x = 0.0;
twist.linear.y = 0.5; // Left translation speed 0.5 m/s
twist.linear.z = 0.0;
twist.angular.x = 0.0;
twist.angular.y = 0.0;
twist.angular.z = 0.0;
pnc.MoveChassis(twist);
std::this_thread::sleep_for(std::chrono::seconds(2));
res = pnc.get_task_state(task_state);
if (res == GDKRes::kSuccess) {
std::cout << "Task state: " << task_state.state << std::endl;
} else {
std::cout << "Failed to get task state" << std::endl;
}
auto task_id = task_state.id;
res = pnc.CancelTask(task_id);
if (res != GDKRes::kSuccess) {
std::cout << "Failed to cancel task" << std::endl;
}
return 0;
}
10. Complete Usage Example¶
- Function: Demonstrates the complete usage workflow of the PNC module
- Example:
#include <iostream>
#include <chrono>
#include <thread>
#include <csignal>
#include "gdk/gdk.h"
void signal_handler(int signum) {
std::cout << "Interrupt signal (" << signum << ") received." << std::endl;
exit(signum);
}
int main(int argc, char** argv) {
if (argc != 8) {
std::cerr << "Usage: " << argv[0]
<< " position_x position_y position_z orientation_x "
"orientation_y orientation_z orientation_w"
<< std::endl;
return 1;
}
double position_x = std::stod(argv[1]);
double position_y = std::stod(argv[2]);
double position_z = std::stod(argv[3]);
double orientation_x = std::stod(argv[4]);
double orientation_y = std::stod(argv[5]);
double orientation_z = std::stod(argv[6]);
double orientation_w = std::stod(argv[7]);
agibot::gdk::Pnc pnc;
std::cout << "Pnc init" << std::endl;
agibot::gdk::NaviReq navi_req;
navi_req.target.position.x = position_x;
navi_req.target.position.y = position_y;
navi_req.target.position.z = position_z;
navi_req.target.orientation.x = orientation_x;
navi_req.target.orientation.y = orientation_y;
navi_req.target.orientation.z = orientation_z;
navi_req.target.orientation.w = orientation_w;
std::this_thread::sleep_for(std::chrono::seconds(1));
auto res = pnc.NormalNavi(navi_req);
if (res != agibot::gdk::GDKRes::kSuccess) {
std::cerr << "NormalNavi failed" << std::endl;
return 1;
}
// std::this_thread::sleep_for(std::chrono::seconds(1));
// Get the task ID
agibot::gdk::PNCTaskState task_state;
res = pnc.GetTaskState(task_state);
if (res != agibot::gdk::GDKRes::kSuccess) {
std::cerr << "GetTaskState failed" << std::endl;
return 1;
}
uint32_t task_id = task_state.id;
std::cout << "PauseTask" << std::endl;
res = pnc.PauseTask(task_id);
if (res != agibot::gdk::GDKRes::kSuccess) {
std::cerr << "PauseTask failed" << std::endl;
return 1;
}
std::cout << "ResumeTask" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
res = pnc.ResumeTask(task_id);
if (res != agibot::gdk::GDKRes::kSuccess) {
std::cerr << "ResumeTask failed" << std::endl;
return 1;
}
std::cout << "CancelTask" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
res = pnc.CancelTask(task_id);
if (res != agibot::gdk::GDKRes::kSuccess) {
std::cerr << "CancelTask failed" << std::endl;
return 1;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
if (res != agibot::gdk::GDKRes::kSuccess) {
// until ctrl c to exit
std::signal(SIGINT, signal_handler);
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
}
Usage Notes¶
- Initialization wait: After creating a Pnc object, it is recommended to wait for a period of time to ensure the system initialization is complete
- Map preparation: Ensure a usable map is available before executing navigation
- Target point setting: Pay attention to the correctness of the coordinate system when setting the target point
- Task state monitoring: It is recommended to periodically check the task state to track navigation progress
- Task management: Use the pause, resume, and cancel functions appropriately
- Precision selection: Choose the appropriate navigation precision (normal/high-precision) according to your needs
- Relative movement: Pay attention to the reasonableness of the movement distance when using relative movement
Application Scenarios¶
- Autonomous navigation: Implement autonomous path planning and navigation for the robot
- Precise navigation: Perform high-precision position control
- Relative movement: Perform relative movement based on the current position
- Task scheduling: Manage the execution of multiple navigation tasks
- Path planning: Plan the optimal path for the robot
- Obstacle-avoidance navigation: Perform safe navigation in complex environments
- Multi-target navigation: Implement continuous navigation across multiple target points
- Remote control: Support navigation in remote control mode