Skip to content

PND CPP SDK

Introduction

The PND cpp sdk is developed based on the C++14 standard and provides a simple and flexible way to operate PND devices (PSA, RCU, PNDEncoder). It includes functions such as reading and writing PSA parameters, controlling PSA movement, reading and writing RCU parameters, and reading the angle of PNDEncoder.

English Name Description
PSA The PSA series actuators have high - communication, high - torque - density, integrated, and standardized joint components. They provide intelligent one - stop solutions for segmented industries, jointly create industry - benchmark cases, and are designed specifically for robotic applications.
RCU The RCU is a power supply module that supports the power supply of PSA - series actuators. It integrates functions such as EthernetUDP communication configuration and power braking. It supports multiple standard RJ45 communication interfaces and a variety of power - output interfaces and can provide reliable guarantees for the different power requirements of multiple actuators.
PNDEncoder It is a module that provides end - position detection for the PNDbotics robot - joint actuators. It has functions such as Ethernet or Wi - Fi communication configuration and obtaining the absolute angle and can provide the absolute - position information of the joint end for the robot master - control system.

Supported Platforms

The Linux x64 platform is recommended. Other platforms have not been fully verified.

  • Linux
    • x64
    • arm32
    • arm64
  • MacOS
    • x64
    • arm64

Examples

Search for Devices on the Network

ol_lookup.cpp
#include <iostream>
#include <thread>

#include "lookup.hpp"

using namespace Pnd;

int main() {
    std::string str("10.10.10.255");
    pndSetLogLevel("INFO", "INFO");
    Lookup lookup(&str);
    // After construction, start the background thread to look up actuators. Wait for 1 second for the module list to be populated, and
    // then print out its contents.
    std::this_thread::sleep_for(std::chrono::seconds(1));
    lookup.setLookupFrequencyHz(0);  // Set lookup to stop.

    std::shared_ptr<Group> group = lookup.getGroupFromFamily("Default");
    if (!group) {
        std::cout << "Group not found! Check that the family and name of a module "
                     "on the network"
                  << std::endl
                  << "matches what is given in the source file." << std::endl;
        return -1;
    }
    std::cout << std::endl << "group size: " << group->size() << std::endl;

    group = lookup.getGroupFromFamily("PNDriver");
    std::cout << std::endl << "PNDriver group size: " << group->size() << std::endl;

    auto entry_list = lookup.getEntryList();
    for (const auto &entry : *entry_list) {
        std::cout << "Name: " << entry.name_ << std::endl;
        std::cout << "Family: " << entry.family_ << std::endl;
    }
    return 0;
}

Use the following commands to search for devices on the network:

$ cd examples/project/cmake
$ cmake -B build
$ cmake --build build -j7
$ cd ../../bin
$./01_lookup
[2024-01-17 14:21:10.091] [info] [t 6291581] Broadcast: 10.10.10.255
[2024-01-17 14:21:10.592] [info] [t 6291585] abs broadcast start.

group size: 1

PNDriver group size: 1
Name: RCU0
Family: RCU
Name: PNDriver1
Family: PNDriver
Name: IO2
Family: IO
Name: PNDencoder3
Family: PNDencoder

PSA Control

Position Control

position_pt.cpp
#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>

#include "groupCommand.hpp"
#include "groupFeedback.hpp"
#include "lookup.hpp"

using namespace Pnd;

int main() {
    std::string str("10.10.10.255");
    pndSetLogLevel("ERROR", "INFO");
    // After construction, start the background thread to look up actuators.
    Lookup lookup(&str);
    // Wait for 1 second for the module list to be populated, and then print out its contents.
    std::this_thread::sleep_for(std::chrono::seconds(1));
    lookup.setLookupFrequencyHz(0);

    auto group = lookup.getGroupFromFamily("Default", 150);

    if (!group) {
        std::cout << "Group not found! Check that the family and name of a module "
                     "on the network"
                  << std::endl
                  << "matches what is given in the source file." << std::endl;
        return -1;
    }

    std::cout << "group size: " << group->size() << std::endl;
    GroupCommand group_command(group->size());

    GroupFeedback group_feedback(group->size());

    group_command.enable(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    auto ret = group->getNextFeedback(group_feedback, 10);
    if (ret) {
        for (int i = 0; i < group_feedback.size(); ++i) {
            if (group_feedback[i]->enabled) {
                std::cout << "disable failed!" << std::endl;
                exit(-1);
            }
        }
    }

    group_command.resetLinearCount(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);

    group_command.enable(std::vector<float>(group->size(), 1));
    group->sendCommand(group_command);

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    ret = group->getNextFeedback(group_feedback, 10);
    if (ret) {
        for (int i = 0; i < group_feedback.size(); ++i) {
            if (!group_feedback[i]->enabled) {
                std::cout << "enable failed!" << std::endl;
                exit(-1);
            }
        }
    }

    std::vector<PosPtInfo> pos_pt_infos;
    std::vector<PosPtInfo> pre_pos_infos;
    PosPtInfo pos;
    int timeout_num = 0;
    int next_feedback_timeout = 0;

    for (int j = 0; j < 10000; ++j) {
        ret = group->getNextFeedback(group_feedback, 10);
        if (!ret) { // Failed to get the next feedback.
            next_feedback_timeout++;
            continue;
        }
        for (int i = 0; i < group_feedback.size(); ++i) {
            if (std::isnan(group_feedback[i]->position)) { // Timeout.
                timeout_num++;
                pos.pos = pre_pos_infos.at(i).pos;
            } else {
                pos.pos = sin(j * 0.002 * M_PI) * 3;
            }
            pos.vel_ff = 0.0;
            pos.torque_ff = 0.0;
            pos_pt_infos.push_back(pos);
        }
        pre_pos_infos = pos_pt_infos;
        group_command.setInputPositionPt(pos_pt_infos);
        group->sendCommand(group_command);
        pos_pt_infos.clear();
        std::cout << "sdk command duration:" << group_feedback.Duration() << " us" << std::endl;

        std::this_thread::sleep_for(std::chrono::milliseconds(4));
    }

    group_command.enable(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);
    std::cout << "feedback timeout:" << next_feedback_timeout << " recv timeout:" << timeout_num << std::endl;

    return 0;
}

Velocity Control

velocity_pt.cpp
#include <iostream>
#include <thread>

#include "groupCommand.hpp"
#include "groupFeedback.hpp"
#include "lookup.hpp"

using namespace Pnd;

int main() {
    std::string str("10.10.10.255");

    // After construction, start the background thread to look up actuators.
    Lookup lookup(&str);

    // Wait for 1 second for the module list to be populated, and then print out its contents.
    std::this_thread::sleep_for(std::chrono::seconds(1));
    lookup.setLookupFrequencyHz(0);  // Set lookup to stop.

    std::shared_ptr<Group> group = lookup.getGroupFromFamily("Default");
    std::cout << std::endl << "group size: " << group->size() << std::endl;
    GroupCommand group_command(group->size());

    group_command.enable(std::vector<float>(group->size(), 1));
    group->sendCommand(group_command);
    // std::this_thread::sleep_for(std::chrono::seconds(1));

    group_command.setInputVelocityPt(std::vector<float>(group->size(), 10));
    group->sendCommand(group_command);
    std::this_thread::sleep_for(std::chrono::seconds(1));

    group_command.setInputVelocityPt(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);
    std::this_thread::sleep_for(std::chrono::seconds(1));

    for (int i = 1; i < 1000; ++i) {
        group_command.setInputVelocityPt(std::vector<float>(group->size(), i / 50.0));
        group->sendCommand(group_command);
        std::this_thread::sleep_for(std::chrono::milliseconds(4));
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));

    group_command.setInputVelocityPt(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);

    group_command.enable(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);

    return 0;
}

Current Control

torque_pt.cpp
#include <iostream>
#include <thread>

#include "groupCommand.hpp"
#include "groupFeedback.hpp"
#include "lookup.hpp"

using namespace Pnd;

int main() {
    std::string str("10.10.10.255");

    // After construction, start the background thread to look up actuators.
    Lookup lookup(&str);

    // Wait for 1 second for the module list to be populated, and then print out its contents.
    std::this_thread::sleep_for(std::chrono::seconds(1));
    lookup.setLookupFrequencyHz(0);  // Set lookup to stop.

    std::shared_ptr<Group> group = lookup.getGroupFromFamily("Default");
    std::cout << std::endl << "group size: " << group->size() << std::endl;
    GroupCommand group_command(group->size());

    group_command.enable(std::vector<float>(group->size(), 1));
    group->sendCommand(group_command);
    std::this_thread::sleep_for(std::chrono::seconds(1));

    for (int i = 1; i < 6; ++i) {
        group_command.setInputTorquePt(std::vector<float>(group->size(), i));
        group->sendCommand(group_command);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));

    group_command.setInputTorquePt(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);

    group_command.enable(std::vector<float>(group->size(), 0));
    group->sendCommand(group_command);
    std::this_thread::sleep_for(std::chrono::seconds(1));

    return 0;
}

RCU Control

rcu.cpp
#include <iostream>
#include <thread>

#include "groupCommand.hpp"
#include "groupFeedback.hpp"
#include "lookup.hpp"

using namespace Pnd;

int main() {
  std::string str("10.10.10.255");
  Lookup lookup(&str);
  // After construction,start the background thread lookup actuator
  // Wait 1 seconds for the module list to populate, and then print out its
  // contents
  std::this_thread::sleep_for(std::chrono::seconds(1));
  lookup.setLookupFrequencyHz(0);  // set lookup stop

  std::shared_ptr<Group> group = lookup.getGroupFromFamily("RCU");
  if (!group) {
    std::cout << "Group not found! Check that the family and name of a module "
                 "on the network"
              << std::endl
              << "matches what is given in the source file." << std::endl;
    return -1;
  }
  std::cout << std::endl << "rcu group size: " << group->size() << std::endl;

  auto command = std::make_shared<GroupCommand>(group->size());
  auto feedback = std::make_shared<GroupFeedback>(group->size());

  bool flag = false;

  command->RcuPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuAV5VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VAPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VBPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->Rcu12VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuFan12VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->Rcu19VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  RcuBrake rcu_brake;
  rcu_brake.brake_enable = false;
  rcu_brake.brake_overvoltage = 49.1;
  rcu_brake.brake_factor = 2049;
  std::vector<RcuBrake> rcu_brake_vec;
  for (int i = 0; i < group->size(); ++i) rcu_brake_vec.push_back(rcu_brake);
  command->RcuBrakeCmd(rcu_brake_vec);
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuAdcOffset(std::vector<float>(group->size(), 42));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  std::this_thread::sleep_for(std::chrono::seconds(2));

  flag = !flag;
  command->RcuPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuAV5VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VAPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuV5VBPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->Rcu12VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuFan12VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->Rcu19VPower(std::vector<bool>(group->size(), flag));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  rcu_brake.brake_enable = true;
  rcu_brake.brake_overvoltage = 49.0;
  rcu_brake.brake_factor = 2048;
  rcu_brake_vec.clear();
  for (int i = 0; i < group->size(); ++i) rcu_brake_vec.push_back(rcu_brake);
  command->RcuBrakeCmd(rcu_brake_vec);
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  command->RcuAdcOffset(std::vector<float>(group->size(), 0));
  group->sendCommand(*command);
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  return 0;
}

PNDEncoder Control

encoder.cpp
#include <iostream>
#include <thread>

#include "groupCommand.hpp"
#include "groupFeedback.hpp"
#include "lookup.hpp"

using namespace Pnd;

int main() {
  std::string str("10.10.10.255");
  Lookup lookup(&str);
  // After construction,start the background thread lookup actuator
  // Wait 1 seconds for the module list to populate, and then print out its
  // contents
  std::this_thread::sleep_for(std::chrono::seconds(1));
  lookup.setLookupFrequencyHz(0);  // set lookup stop
  pndSetLogLevel(NULL, NULL);

  std::shared_ptr<Group> group = lookup.getGroupFromFamily("PNDencoder");
  if (!group) {
    std::cout << "Group not found! Check that the family and name of a module "
                 "on the network"
              << std::endl
              << "matches what is given in the source file." << std::endl;
    return -1;
  }
  std::cout << std::endl << "group size: " << group->size() << std::endl;

  GroupCommand group_command(group->size());
  GroupFeedback group_feedback(group->size());
  group_command.getEncoderAngle(std::vector<float>(group->size(), 1));

  auto startTime = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::seconds(100);
  while (std::chrono::high_resolution_clock::now() - startTime < duration) {
    group->sendCommand(group_command);
    auto ret = group->getNextFeedback(group_feedback, 10);
    if (ret) {
      for (int i = 0; i < group_feedback.size(); ++i) {
        std::cout << group_feedback[i]->encoder_angle << std::endl;
      }
    } else {
      std::cout << "getNextFeedback failed!" << std::endl;
      exit(-1);
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
  }

  return 0;
}

Interface Description

CPP

Lookup

The function of the Lookup class below is to search for all devices on the network, and obtain a group of control devices through the getGroupXXX functions.

lookup.hpp
#pragma once
#include <memory>

#include "aios.h"
#include "group.hpp"
#include "util.hpp"

namespace Pnd {

/**
 * @brief Maintains a registry of network-connected modules and returns Group
 * objects to the user.
 *
 * Only one Lookup object is needed per application.
 */
class Lookup final {
 public:
  /**
   * @brief Creates a Lookup object which can create Module and Group
   * references.
   * Typically, only one Lookup object should exist at a time.
   *
   * Note that this call invokes a background thread to query the network for
   * modules at regular intervals.
   */
  Lookup(std::string *addr = nullptr);

  /**
   * @brief Destructor frees all resources created by Lookup object, and stops
   * the background query thread.
   */
  ~Lookup() noexcept;

  /**
   * @brief Sets the broadcast address for the lookup.
   *
   * @param networks A string pointer to a broadcast address.
   *             eg: "192.168.100.255,192.168.101.255"
   */
  void setNetWorks(std::string networks);

  /**
   * @brief Get CtrlBox ip address.
   */
  std::string getCtrlBoxIP();

  /**
   * @brief Get a group from all known modules with the given family.
   *
   * @param family The family of each of the desired group modules.
   * @returns A shared_ptr with no reference if no group found in allotted
   * time, or reference to a newly allocated group object corresponding to
   * the given parameters otherwise.
   */
  std::shared_ptr<Group> getGroupFromFamily(const std::string &family, int32_t timeout_ms = DEFAULT_TIMEOUT);

  std::shared_ptr<Group> getGroupFromIps(const std::vector<std::string> &ips);

  /**
   * @brief Gets the rate [Hz] at which "discovery" packets are broadcast.
   *
   * Defaults to 5 Hz.
   */
  float getLookupFrequencyHz() const;

  /**
   * @brief Sets the lookup rate [Hz]
   *
   * @param frequency The rate at which "discovery" packets get broadcast on
   * the network to search for modules.
   *
   * \returns true on success, false on failure (e.g., invalid frequency)
   */
  bool setLookupFrequencyHz(float frequency);

  class EntryList final {
    struct Entry final {
      std::string name_;
      std::string family_;
      std::string serial_number_;
    };

   private:
    /**
     * \internal C-style lookup entry list object
     */
    PndLookupEntryListPtr lookup_list_;

    /**
     * \internal Entry list iterator implementation
     * (see http://anderberg.me/2016/07/04/c-custom-iterators/)
     */
    class Iterator final {
     public:
      // Iterator traits (not from std::iterator to be C++17 compliant)
      using value_type = Entry;
      using difference_type = int;
      using pointer = Entry *;
      using reference = Entry;
      using iterator_category = std::bidirectional_iterator_tag;

      Iterator() = delete;
      explicit Iterator(const EntryList &list, size_t current);

      reference operator*() const;

      Iterator &operator++();
      Iterator operator++(int);
      Iterator &operator--();
      Iterator operator--(int);

      bool operator==(const Iterator &rhs) const;
      bool operator!=(const Iterator &rhs) const;

     private:
      const EntryList &list_;
      size_t current_{0};
    };

   public:
    /**
     * \internal Creates entry list from internal C-style object.
     */
    EntryList(PndLookupEntryListPtr lookup_list) : lookup_list_(lookup_list) {}

    ~EntryList() noexcept;

    Entry operator[](size_t index) const;

    size_t size() const;

    Iterator begin() const;
    Iterator end() const;

   private:
    /**
     * Disable copy and move constructors and assignment operators
     */
    PND_DISABLE_COPY_MOVE(EntryList)
  };

  std::shared_ptr<EntryList> getEntryList();

  DeviceList *getDeviceList();

 private:
  /**
   * \internal C-style lookup object
   */
  PndLookupPtr lookup_;

  static const int32_t DEFAULT_TIMEOUT = 500;
};

}  // namespace Pnd

Group

The function of the Group class below is to organize several devices of the same type (PSA, RCU, PNDEncoder) into a group for synchronous control.

group.hpp
#pragma once

#include <functional>
#include <memory>
#include <mutex>
#include <vector>

#include "aios.h"

namespace Pnd {

class GroupFeedback;
class GroupCommand;

using GroupFeedbackHandler = std::function<void(const GroupFeedback &)>;

/**
 * @brief Represents a group of physical Pnd actuator, and allows Command,
 * Feedback, and Info objects to be sent to and recieved from the actuator.
 */
class Group final {
 public:
  /**
   * Creates a group from the underlying C-style group object. This should
   * only be called to create groups from the lookup class, not from user
   * code!
   */
  Group(PndGroupPtr group, float initial_feedback_frequency = 0.0f, int32_t initial_command_lifetime = 0);

  /**
   * @brief Destructor cleans up group.
   */
  ~Group() noexcept;

  /**
   * @brief Returns the number of modules in the group
   */
  int size();

  /**
   * @brief Sets the command lifetime for the modules in this group.
   */
  bool setCommandLifetimeMs(int32_t ms);

  /**
   * @brief Send a command to the given group, requesting an acknowledgement
   * of transmission to be sent back.
   *
   * @param group_command The GroupCommand object containing information to be
   * sent to the group.
   *
   * @returns true if an acknowledgement was successfully received
   * (guaranteeing the group received this command), or a negative number for
   * an error otherwise.
   */
  bool sendCommand(const GroupCommand &group_command);

  /**
   * @brief Requests feedback from the group.
   *
   * Sends a background request to the modules in the group; if/when all
   * modules return feedback, any associated handler functions are called.
   * This returned feedback is also stored to be returned by the next call to
   * getNextFeedback (any previously returned data is discarded).
   *
   * @returns @c true if feedback was request was successfully sent, otherwise
   *  @c false on failure (i.e., connection error).
   */
  bool sendFeedbackRequest(PndFeedbackCode feedbackCode = PndFeedbackAll);

  /**
   * @brief Returns the most recently stored feedback from a sent feedback
   * request, or returns the next one received (up to the requested timeout).
   *
   * Note that a feedback request can be sent either with the
   * sendFeedbackRequest function.
   *
   * Warning: other data in the provided 'Feedback' object is erased!
   *
   * @param feedback On success, the group feedback read from the group are
   * written into this structure.
   *
   * @returns @c true if feedback was returned, otherwise @c false on failure
   * (i.e., connection error or timeout waiting for response).
   */
  bool getNextFeedback(GroupFeedback &feedback, int32_t timeout_ms = DEFAULT_TIMEOUT_MS);

  /**
   * TODO:
   * @brief Sets the frequency of the internal feedback request + callback
   * thread.
   *
   * @returns @c true if the frequency successfully was set, or @c false
   * if the parameter was outside the accepted range (less than zero or faster
   * than supported maximum).
   */
  bool setFeedbackFrequencyHz(float frequency);

  /**
   * TODO:
   */
  float getFeedbackFrequencyHz();

  /**
   * TODO:
   */
  void addFeedbackHandler(GroupFeedbackHandler handler);

  /**
   * TODO:
   */
  void clearFeedbackHandlers();

  /**
   * @brief Gets the actuator error message
   */
  PndFeedbackErrorPtr getError(int idx);

 private:
  /**
   * C-style group object
   */
  PndGroupPtr internal_;

  /**
   * The number of modules in this group.
   */
  const int number_of_modules_;

  /**
   * Protects access to the group feedback handler vector.
   */
  std::mutex handler_lock_;

  /**
   * TODO:
   */
  std::vector<GroupFeedbackHandler> handlers_;

  /**
   * TODO:
   */
  friend void callbackWrapper(PndGroupFeedbackPtr group_feedback, void *user_data);

  /**
   * TODO:
   */
  void callAttachedHandlers(PndGroupFeedbackPtr group_feedback);

 public:
  static const int32_t DEFAULT_TIMEOUT_MS = 500;
};

}  // namespace Pnd

GroupCommand

The function of the GroupCommand class below is to construct control commands for a group of devices.

groupCommand.hpp
#pragma once

#include <memory>
#include <vector>

#include "aios.h"

namespace Pnd {

/**
 * @brief A list of Command objects appropriate for sending to a Group of
 * modules; the size() must match the number of modules in the group.
 */
class GroupCommand final {
 public:
  /**
   * @brief Create a group command with the specified number of modules.
   */
  GroupCommand(size_t number_of_modules);

  /**
   * @brief Destructor cleans up group command object as necessary.
   */
  ~GroupCommand() noexcept;

  /**
   * @brief Returns the number of module commands in this group command.
   */
  size_t size() const;

  /**
   * @brief Access the command for an individual module.
   */
  PndCommandPtr operator[](size_t index);

  /**
   * @brief Access the command for an individual module.
   */
  const PndCommandPtr operator[](size_t index) const;

  /**
   * @brief Clears all data in this GroupCommand object; this returns to the
   * state the GroupCommand was at time of creation.
   */
  void clear();

  /**
   * @brief Convenience function for setting position commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setPosition(const std::vector<float> &position);

  /**
   * @brief Convenience function for setting TrapezoidalMove commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setTrapezoidalMove(const std::vector<float> &val);

  /**
   * @brief Convenience function for setting velocity commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setVelocity(const std::vector<float> &velocity);

  /**
   * @brief Convenience function for setting velocity ramp commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setVelocityRamp(const std::vector<float> &velocity);

  /**
   * @brief Convenience function for setting current commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setCurrent(const std::vector<float> &effort);

  /**
   * @brief Convenience function for setting enable commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   * enable is (nan continue, 0 disable, 1 enable),so choose float type.
   */
  void enable(const std::vector<float> &status);

  /**
   * @brief Convenience function for setting reboot commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void reboot(const std::vector<bool> &flag);

  /**
   * @brief Convenience function for setting getError commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void getError(const std::vector<bool> &flag);

  /**
   * @brief Convenience function for setting clearError commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void clearError(const std::vector<bool> &flag);

  /**
   * @brief Convenience function for setting resetLinearCount commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void resetLinearCount(const std::vector<float> &linearCount);

  /**
   * @brief Convenience function for setting setMotionCtrlConfig commands
   * from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setMotionCtrlConfig(const std::vector<MotionControllerConfig *> &config);

  /**
   * @brief Convenience function for setting setMotorConfig commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setMotorConfig(const std::vector<MotorConfig *> &config);

  /**
   * @brief Convenience function for setting setTrapTraj commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setTrapTraj(const std::vector<TrapTraj *> &config);

  /**
   * @brief Convenience function for setting saveConfig commands from vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void saveConfig(const std::vector<bool> &flag);

  /**
   * @brief Convenience function for setting setNetworkSetting commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void setNetworkSetting(const std::vector<NetworkSetting *> &config);

  // For latency test
  void setLatencyTest(const std::vector<bool> &flag);

  /******* fw2 .0 *******/
  void setInputPositionPt(const std::vector<PosPtInfo> &param);

  void setInputVelocityPt(const std::vector<float> &param);

  void setInputTorquePt(const std::vector<float> &param);
  /******* fw2 .0 *******/

  /**
   * @brief Convenience function for setting ctrlBoxEnable commands from
   * vectors.
   *
   * Note that if the vector is not the correct link, no action is taken.
   */
  void RcuPower(const std::vector<bool> &status);
  void RcuAV5VPower(const std::vector<bool> &status);
  void RcuV5VPower(const std::vector<bool> &status);
  void RcuV5VAPower(const std::vector<bool> &status);
  void RcuV5VBPower(const std::vector<bool> &status);
  void Rcu12VPower(const std::vector<bool> &status);
  void RcuFan12VPower(const std::vector<bool> &status);
  void Rcu19VPower(const std::vector<bool> &status);

  void RcuBrakeCmd(const std::vector<RcuBrake> &param);
  void RcuAdcOffset(const std::vector<float> &param);
  void RcuFwUpgrade();

  // Encoder
  void getEncoderAngle(const std::vector<float> &param);

 public:
  /**
   * C-style group command object.
   * NOTE: this should not be used except by library functions!
   */
  PndGroupCommandPtr internal_;

  /**
   * The number of modules in this group command.
   */
  const size_t number_of_modules_;

 private:
  /**
   * The list of Command subobjects
   */
  std::vector<PndCommandPtr> commands_;
};

}  // namespace Pnd

GroupFeedback

The function of the GroupFeedback class below is to obtain the feedback of a group of devices.

groupFeedback.hpp
#pragma once

#include <vector>

#include "aios.h"

namespace Pnd {

/**
 * @brief A list of Feedback objects that can be received from a Group of
 * modules; the size() must match the number of modules in the group.
 */
class GroupFeedback final {
 public:
  /**
   * @brief Create a group feedback with the specified number of modules.
   */
  GroupFeedback(size_t number_of_modules);

  /**
   * TODO:
   */
  GroupFeedback(PndGroupFeedbackPtr group_feedback);

  /**
   * @brief Destructor cleans up group feedback object as necessary.
   */
  ~GroupFeedback() noexcept;

  /**
   * @brief Returns the number of module feedbacks in this group feedback.
   */
  size_t size() const;

  /**
   * @brief Access the feedback for an individual module.
   */
  const PndFeedbackPtr &operator[](size_t index) const;

  /**
   * @brief Get the duration of the command sent to recv.
   */
  const int Duration() { return pndGroupFeedbackGetDuration(internal_); };

 public:
  /**
   * C-style group feedback object.
   * NOTE: this should not be used except by library functions!
   */
  PndGroupFeedbackPtr internal_;

 private:
  /**
   * True if this object is responsible for creating and destroying the
   * underlying C pointer; false otherwise.
   */
  const bool manage_pointer_lifetime_;

  /**
   * The number of modules in this group feedback.
   */
  const size_t number_of_modules_;

  /**
   * The list of Feedback subobjects
   */
  std::vector<PndFeedbackPtr> feedbacks_;
};

}  // namespace Pnd

error code

Value Description
48 Feed forward change rate is too large
64 Over current limit

Release Notes

v1.5.11

v1.5.1

Fixed

  • fix array overreach caused by names

v1.4.4

v1.4.4-auth

v1.4.32

v1.4.3

Fixed

  • fix some bug

v1.4.3-auth3

v1.4.3-auth

Features

  • add auth

v1.4.24

v1.4.2

Fixed

  • fix mutil group control error

v1.4.15

v1.4.1

Features

  • Add get all device list api for c/c++

  • Find the io device in the broadcast

Docs

  • Add doc for aios.h

v1.4.06

v1.4.0

Features

  • Add create group form ips

  • Add rcu brake and rcu adcoffset api

  • Add rcu power api

  • Add Rcu av5v power

  • Add rcu power

v1.3.07

v1.3.0

Features

  • Add encoder related.

Docs

  • Update latency_test.

v1.2.08

v1.2.0

Features

  • Control console and file log levels.

v1.1.09

v1.1.0

Features

  • Add duration of the command sent to recv

v1.0.010

v1.1.0

  • base version


  1. Fixed

    • fix array overreach caused by names

  2. Fixed

    • fix some bug

  3. Features

    • add auth

  4. Fixed

    • fix mutil group control error

  5. Features

    • Add get all device list api for c/c++
    • Find the io device in the broadcast

    Docs

    • Add doc for aios.h

  6. Features

    • Add create group form ips
    • Add rcu brake and rcu adcoffset api
    • Add rcu power api
    • Add Rcu av5v power
    • Add rcu power

  7. Features

    • Add encoder related.

    Examples

    • Update latency_test.

  8. Features

    • Control console and file log levels.

  9. Features

    • Add duration of the command sent to recv

    • base version