libfranka——motion_with_control.cpp例程解析

motion_with_control.cpp例程解析

核心代码:

class Controller {
 public:
  /**
   * @brief Construct a new Controller object
   *
   * @param dq_filter_size 滤波器缓冲器大小
   * @param K_P PD控制参数
   * @param K_D PD控制参数
   */
  Controller(size_t dq_filter_size,
             const std::array<double, 7>& K_P,  // NOLINT(readability-identifier-naming)
             const std::array<double, 7>& K_D)  // NOLINT(readability-identifier-naming)
      : dq_current_filter_position_(0), dq_filter_size_(dq_filter_size), K_P_(K_P), K_D_(K_D) {
    std::fill(dq_d_.begin(), dq_d_.end(), 0);                      // set all dq_d_ zero
    dq_buffer_ = std::make_unique<double[]>(dq_filter_size_ * 7);  // dq缓冲器(生成智能指针)
    std::fill(&dq_buffer_.get()[0], &dq_buffer_.get()[dq_filter_size_ * 7],
              0);  // set all dq_buffer_ zero
  }

  // 内联函数
  /**
   * @brief 7个关节的力矩控制律(PD控制),返回关节力矩
   *
   * @param state 机器人状态
   * @return franka::Torques 关节力矩
   */
  inline franka::Torques step(const franka::RobotState& state) {
    updateDQFilter(state);

    std::array<double, 7> tau_J_d;  // NOLINT(readability-identifier-naming)
    // 7个关节的力矩控制律(PD控制)
    for (size_t i = 0; i < 7; i++) {
      tau_J_d[i] = K_P_[i] * (state.q_d[i] - state.q[i]) + K_D_[i] * (dq_d_[i] - getDQFiltered(i));
    }
    return tau_J_d;
  }

  /**
   * @brief 更新DQ滤波器dq_buffer_内的数据
   *
   * @param state
   */
  void updateDQFilter(const franka::RobotState& state) {
    // 获取7个关节的速度
    for (size_t i = 0; i < 7; i++) {
      dq_buffer_.get()[dq_current_filter_position_ * 7 + i] = state.dq[i];
    }
    // 当前滤波器所指向的位置,标志位
    dq_current_filter_position_ = (dq_current_filter_position_ + 1) % dq_filter_size_;
  }

  /**
   * @brief 从dq_buffer_中求某一关节前5个时间的关节速度平均值
   *
   * @param index 关节索引,代表哪一个关节
   * @return double 关节速度平均值
   */
  double getDQFiltered(size_t index) const {
    double value = 0;
    for (size_t i = index; i < 7 * dq_filter_size_; i += 7) {
      value += dq_buffer_.get()[i];
    }
    return value / dq_filter_size_;
  }

 private:
  size_t dq_current_filter_position_;
  size_t dq_filter_size_;

  const std::array<double, 7> K_P_;  // NOLINT(readability-identifier-naming)
  const std::array<double, 7> K_D_;  // NOLINT(readability-identifier-naming)

  std::array<double, 7> dq_d_;           // 期望的关节速度
  std::unique_ptr<double[]> dq_buffer_;  // 关节
};

/**
 * @brief 生成梯形速度轨迹
 *
 * @param a_max 最大加速度
 * @return std::vector<double> 
 */
std::vector<double> generateTrajectory(double a_max) {
  // Generating a motion with smooth velocity and acceleration.
  // 以平滑的速度和加速度产生运动
  // Squared sine is used for the acceleration/deceleration phase.
  // 平方正弦用于加速/减速阶段
  std::vector<double> trajectory;
  constexpr double kTimeStep = 0.001;  // [s] 时间步长
  constexpr double kAccelerationTime = 1;  // time spend accelerating and decelerating [s] 加速和减速的时间
  constexpr double kConstantVelocityTime = 1;  // time spend with constant speed [s] 匀速的时间

  // obtained during the speed up and slow down [rad/s^2]
  double a = 0;  // [rad/s^2]
  double v = 0;  // [rad/s]
  double t = 0;  // [s]
  
  // 当时间小于运动总时间(加减速时间 + 匀速时间)
  while (t < (2 * kAccelerationTime + kConstantVelocityTime)) {
    // 在加速阶段
    if (t <= kAccelerationTime) {
      a = pow(sin(t * M_PI / kAccelerationTime), 2) * a_max;
      // 在匀速阶段
    } else if (t <= (kAccelerationTime + kConstantVelocityTime)) {
      a = 0;
      // 在减速阶段
    } else {
      const double deceleration_time = (kAccelerationTime + kConstantVelocityTime) - t;  // 减速阶段花费的时间
      a = -pow(sin(deceleration_time * M_PI / kAccelerationTime), 2) * a_max;
    }
    v += a * kTimeStep; // 速度为加速度对时间的积分
    t += kTimeStep; // 时间累加
    trajectory.push_back(v); // 轨迹生成
  }
  return trajectory;
}

提出问题:

  • 这个例程实现了什么功能?——使用DQ滤波器对关节速度进行滤波,使得关节运动更加平稳。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值