Skip to content

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. Returns GDKRes::kSuccess on success; the task_state parameter 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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. Returns GDKRes::kSuccess on 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

  1. Initialization wait: After creating a Pnc object, it is recommended to wait for a period of time to ensure the system initialization is complete
  2. Map preparation: Ensure a usable map is available before executing navigation
  3. Target point setting: Pay attention to the correctness of the coordinate system when setting the target point
  4. Task state monitoring: It is recommended to periodically check the task state to track navigation progress
  5. Task management: Use the pause, resume, and cancel functions appropriately
  6. Precision selection: Choose the appropriate navigation precision (normal/high-precision) according to your needs
  7. 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