Skip to content

使用 servo_move() 来进行跟踪运动

servo_move(SOCKETFD socketFd,ServoMovePara servoMove) 可以接收一组点,然后将接收到的点位根据 timeStamp做平滑处理后下发到伺服运动。

cpp
struct ServoMovePara {
  ///< 传输参数
  bool clearBuffer;                         ///< 是否清除之前发送的,未开始插补计算的点位
  int targetMode;                           ///< 0-独立点 1-连续轨迹
  int sendMode;                             ///< 0-一次传输完全部轨迹 1-一次传输部分点位
  int runMode;                              ///< 0-接收完再运动 1-边接受边运动
  int sum;                                  ///< 总传输次数
  int count;                                ///< 当前是第几次传输
  ///< 运动参数
  int coord;                                ///< 0-关节 1-直角
  int size;                                 ///< 本次传输的点位数
  std::vector<std::vector<double>> pos;     ///< 二维数组,一维表示本次传输的点位数,二维长度为7,各个关节角度或笛卡尔坐标
  std::vector<std::vector<double>> axisvel; ///< 二维数组,一维表示本次传输的点位数,二维长度为7,各个轴的速度
  std::vector<std::vector<double>> axisacc; ///< 二维数组,一维表示本次传输的点位数,二维长度为7,各个轴的加速度
  std::vector<double> timeStamp;            ///< 长度为本次传输的点位数,表示到达该点位的时间,单位ms
};

使用前提:需要在示教器上运行外部点的指令

启动运行这个作业文件

示例一:使用连续点位轨迹,每次传输部分点位来进行遥操作

cpp
#include <iostream>
#include <vector>
#include <chrono>
#include "cpp_interface/nrc_api.h"


int main() {
  ServoMovePara param;


  // 目标点位数据
  double axis1_pos = 1;
  double axis2_pos = 2;
  
  // 查询运动前坐标
  std::vector<double> pos(7);
  get_current_position(fd, 0, pos);
  std::cout << "关节运动前坐标:" << pos[0] << " " << pos[1] << " " << pos[2] << " " 
            << pos[3] << " " << pos[4] << " " << pos[5] << " "  << pos[6] << std::endl;
  
  for (int k = 0; k < 4000; k++) {
      // 生成目标点位数据
      for (int i = 0; i < 2; i++) {
          param.pos.push_back({pos[0], pos[1], pos[2], pos[3], pos[4], pos[5], pos[6]});      //目标点位数据
          std::cout << "关节角=" << param.pos[i][6] << std::endl;
  
          if (k < 100) {
              pos[5] += 0.05;
          } else if (k >= 100 && k < 200) {
              pos[5] -= 0.05;
          } else if (k >= 200 && k < 300) {
              pos[5] += 0.05;
          } else {
              pos[5] -= 0.05;
          }
  
          std::cout << "k=" << k << std::endl;
      }
  
      std::cout << "大小=" << param.pos.size() << std::endl;
  
      // 设置每个轴的速度
      for (int i = 0; i < param.pos.size(); i++) {
          param.axisvel.push_back({1, 1, 1, 1, 1, 50, 1});     //到达目标点位的每个轴的速度,单位度每秒
      }
  
      // 设置每个轴的加速度
      for (int i = 0; i < param.pos.size(); i++) {
          param.axisacc.push_back({1, 1, 1, 1, 1, 50, 1});       //到达目标点位的每个轴的加速度
      }
  
      // 设置时间戳
      double times = 5;     //运行到该点位时,相对于起始点的时间
      for (int i = 0; i < param.pos.size(); i++) {
          param.timeStamp.push_back(times);
          times += 5;        //假设后续每一个点位都相较于上一个点多5ms,最终timeStamp数组是{5,10,15,20...}
      }
  
      // 设置参数
      param.clearBuffer = true;  // 使用连续运动时,clearBuffer,targetMode,sendMode,runMode需要按照这个固定格式赋值
      param.targetMode = 0;   // 连续轨迹
      param.sendMode = 0;     // 一次传输完全部轨迹点位
      param.runMode = 0;
      param.coord = 0;        // 关节坐标
      param.sum = 100000;        // 因为需要持续发送点位,我们假设总的发送次数很大
      param.count = 100000;        // 因为需要持续发送点位,我们假设总的发送次数很大
      param.extMove = 0;
      param.size = param.pos.size();
  
      // 调用运动接口
      auto t_start = std::chrono::high_resolution_clock::now();
      std::cout << "servo_move return: " << servo_move(fd, param) << std::endl;
  
      auto t_stop = std::chrono::high_resolution_clock::now();
      auto t_duration = std::chrono::duration<double>(t_stop - t_start);
      std::cout << "t_duration: " << t_duration.count() << std::endl;
  
      // 延时补偿
      if (t_duration.count() < times / 1000 + 0.01) {
          std::this_thread::sleep_for(std::chrono::duration<double>(times / 1000 + 0.01 - t_duration.count()));
      }
  
      // 清空参数
      param.pos.clear();
      param.axisvel.clear();
      param.axisacc.clear();
      param.timeStamp.clear();
  }
  return 0;
}

示例二:使用独立点位轨迹,,一次性传输完全部轨迹点位(没有平滑)

cpp
#include <iostream>
#include <vector>
#include <chrono>
#include "cpp_interface/nrc_api.h"


int main() {
  ServoMovePara param;


// 目标点位数据
double axis1_pos = 1;
double axis2_pos = 2;


// 查询运动前坐标
std::vector<double> pos(7);
get_current_position(fd, 0, pos);
std::cout << "关节运动前坐标:" 
          << pos[0] << " " << pos[1] << " " << pos[2] << " " 
          << pos[3] << " " << pos[4] << " " << pos[5] << " " 
          << pos[6] << std::endl;


for (int k = 0; k < 4000; k++) {
    // 生成目标点位数据
    for (int i = 0; i < 2; i++) {
        param.pos.push_back({pos[0], pos[1], pos[2], pos[3], pos[4], pos[5], pos[6]});      //目标点位数据
        std::cout << "关节角=" << param.pos[i][6] << std::endl;


        if (k < 100) {
            pos[5] += 0.05;
        } else if (k >= 100 && k < 200) {
            pos[5] -= 0.05;
        } else if (k >= 200 && k < 300) {
            pos[5] += 0.05;
        } else {
            pos[5] -= 0.05;
        }


        std::cout << "k=" << k << std::endl;
    }


    std::cout << "大小=" << param.pos.size() << std::endl;


    // 设置每个轴的速度
    for (int i = 0; i < param.pos.size(); i++) {
        param.axisvel.push_back({1, 1, 1, 1, 1, 50, 1});     //到达目标点位的每个轴的速度,单位度每秒
    }


    // 设置每个轴的加速度
    for (int i = 0; i < param.pos.size(); i++) {
        param.axisacc.push_back({1, 1, 1, 1, 1, 50, 1});       //到达目标点位的每个轴的加速度
    }


    // 设置时间戳
    double times = 5;     //运行到该点位时,相对于起始点的时间
    for (int i = 0; i < param.pos.size(); i++) {
        param.timeStamp.push_back(times);
        times += 5;        //假设后续每一个点位都相较于上一个点多5ms,最终timeStamp数组是{500,550,600,650...}
    }


    // 设置参数
    param.robotNum = 1;
    param.clearBuffer = true;  // 使用连续运动时,clearBuffer,targetMode,sendMode,runMode需要按照这个固定格式赋值
    param.targetMode = 0;   // 独立点位
    param.sendMode = 0;     // 一次传输完全部轨迹点位
    param.runMode = 0;
    param.coord = 0;        // 关节坐标
    param.size = param.pos.size();
    // 调用运动接口
    std::cout << "servo_move return: " << servo_move(fd, param) << std::endl;
    // 延时5ms
    std::this_thread::sleep_for(std::chrono::milliseconds(5));


    // 清空参数
    param.pos.clear();
    param.axisvel.clear();
    param.axisacc.clear();
    param.timeStamp.clear();
}
  return 0;
}