首页 > 其他分享 >Franka Robot demo 力控 force_control.cpp

Franka Robot demo 力控 force_control.cpp

时间:2024-07-10 18:09:26浏览次数:14  
标签:control tau Franka force Eigen initial state array

// Copyright (c) 2023 Franka Robotics GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <array>
#include <iostream>

#include <Eigen/Core>

#include <franka/duration.h>
#include <franka/exception.h>
#include <franka/model.h>
#include <franka/robot.h>

#include "examples_common.h"

/**
 * @example force_control.cpp
 * A simple PI force controller that renders in the Z axis the gravitational force corresponding
 * to a target mass of 1 kg.
 *
 * @warning: make sure that no endeffector is mounted and that the robot's last joint is in contact
 * with a horizontal rigid surface before starting.
 */

/**
 * @example force_control.cpp
 * 一个简单的 PI 力控制器,它在 Z 轴上施加相当于 1 kg 目标质量的重力。
 *
 * @警告: 确保在启动前没有安装末端执行器,并且机器人的最后一个关节与水平刚性表面接触。
 */

int main(int argc, char** argv) {
  // Check whether the required arguments were passed // 传入机器人IP参数
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << " <robot-hostname>" << std::endl;
    return -1;
  }
  // parameters
  double desired_mass{0.0};
  constexpr double target_mass{1.0};    // 目标质量 1KG ,用于计算目标重力。 NOLINT(readability-identifier-naming)
  constexpr double k_p{1.0};            // 比例控制器增益,用于控制器中的比例项。 NOLINT(readability-identifier-naming)
  constexpr double k_i{2.0};            // 积分控制器增益,用于控制器中的积分项。 NOLINT(readability-identifier-naming)
  constexpr double filter_gain{0.001};  // 滤波增益,用于对传感器数据进行滤波以减少噪声。 NOLINT(readability-identifier-naming)

  try {
    // connect to robot
    franka::Robot robot(argv[1]);// 与机器人建立通信
    setDefaultBehavior(robot); // 设置机器人默认参数
    // load the kinematics and dynamics model
    franka::Model model = robot.loadModel(); // 加载运动学和动力学模型

    // set collision behavior 设置默认碰撞行为
    robot.setCollisionBehavior({{100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0}},
                               {{100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0}},
                               {{100.0, 100.0, 100.0, 100.0, 100.0, 100.0}},
                               {{100.0, 100.0, 100.0, 100.0, 100.0, 100.0}});

    franka::RobotState initial_state = robot.readOnce();// 读取机器人状态作为初始状态
    // initial_tau_ext 通常用于存储机器人每个关节的初始外部力矩。 tau_error_integral : 通常用于存储积分误差,这在积分控制器(例如 PI 控制器)中非常常见
    Eigen::VectorXd initial_tau_ext(7), tau_error_integral(7); 
    // Bias torque sensor 偏置力矩传感器
    std::array<double, 7> gravity_array = model.gravity(initial_state);// 计算机器人在初始化状态下的重力力矩
    Eigen::Map<Eigen::Matrix<double, 7, 1>> initial_tau_measured(initial_state.tau_J.data());//测量到的关节力矩映射为一个 Eigen 向量
    Eigen::Map<Eigen::Matrix<double, 7, 1>> initial_gravity(gravity_array.data());// 将 gravity_array 数组的数据映射为一个 Eigen 向量
    initial_tau_ext = initial_tau_measured - initial_gravity; // 测量到的关节力矩减去计算得到的重力力矩,来计算机器人受到的外部力矩。

    // init integrator 初始化力距积分误差
    tau_error_integral.setZero();

    // define callback for the torque control loop 定义力距控制循环的回调函数
    Eigen::Vector3d initial_position; // 初始化位置
    double time = 0.0;
    // lambda 函数,用于从机器人的状态中获取末端执行器的位置。
    auto get_position = [](const franka::RobotState& robot_state) {
      return Eigen::Vector3d(robot_state.O_T_EE[12], robot_state.O_T_EE[13],
                             robot_state.O_T_EE[14]);
    };

    // 定义力控回调函数
    auto force_control_callback = [&](const franka::RobotState& robot_state,
                                      franka::Duration period) -> franka::Torques {// 传入机器人状态,周期耗时, 返回力距
      time += period.toSec();

      if (time == 0.0) {
        initial_position = get_position(robot_state); // 获取初始化位置
      }

      //程序开始执行后的某个时间点,机器人的位置已经偏离了初始位置超过 10 毫米
      if (time > 0 && (get_position(robot_state) - initial_position).norm() > 0.01) {
        throw std::runtime_error("Aborting; too far away from starting pose!");
      }

      // get state variables 获取状态变量
      std::array<double, 42> jacobian_array = // 计算并存储了机器人末端执行器的 Jacobian 矩阵,为后续的运动学分析和控制提供了基础数据
          model.zeroJacobian(franka::Frame::kEndEffector, robot_state);

      Eigen::Map<const Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data()); // 转化雅克比矩阵
      Eigen::Map<const Eigen::Matrix<double, 7, 1>> tau_measured(robot_state.tau_J.data()); // 测量的力距
      Eigen::Map<const Eigen::Matrix<double, 7, 1>> gravity(gravity_array.data()); // 重力分量
      // tau_d(7): 这是一个大小为 7 的向量,用于存储期望的关节扭矩。
      // 大小为 6 的向量,用于存储期望的末端执行器力和扭矩。
      // 大小为 7 的向量,用于存储发送给机器人的最终关节扭矩命令。
      // 大小为 7 的向量,用于存储从机器人传感器测量得到的外部作用在关节上的扭矩。
      Eigen::VectorXd tau_d(7), desired_force_torque(6), tau_cmd(7), tau_ext(7); // 
      desired_force_torque.setZero();//初始化末端执行器扭矩
      desired_force_torque(2) = desired_mass * -9.81;//z轴施加1KG物体的重力
      // tau_measured 是从机器人关节传感器测量得到的实际关节扭矩。
      // gravity 是由于重力作用在关节上产生的扭矩。
      // initial_tau_ext 是在机器人启动时测量得到的初始外部扭矩。
      // 得到真正由外部力/扭矩作用在关节上产生的扭矩,也就是 tau_ext
      tau_ext << tau_measured - gravity - initial_tau_ext;
      tau_d << jacobian.transpose() * desired_force_torque; // 计算出期望的关节扭矩  将期望的末端执行器力/扭矩转换成期望的关节扭矩
      tau_error_integral += period.toSec() * (tau_d - tau_ext); // 累加积分误差 期望关节扭矩 - 真正外部关节扭矩
      // FF + PI control
      // tau_d 是期望的关节扭矩。
      // tau_ext 是从传感器测量得到的外部作用在关节上的扭矩。
      // tau_error_integral 是关节扭矩误差的积分项。
      // k_p 和 k_i 是比例和积分控制器的增益系数。
      // 实现了一个基于 PID 反馈控制的关节扭矩闭环控制算法,用于补偿外部载荷,使机器人的实际关节运动更加接近期望运动
      tau_cmd << tau_d + k_p * (tau_d - tau_ext) + k_i * tau_error_integral; // 类似于PID 控制原理 

      // Smoothly update the mass to reach the desired target value
      // 实现了质量值的平滑更新,使其逐步达到目标质量值:
      desired_mass = filter_gain * target_mass + (1 - filter_gain) * desired_mass;

      std::array<double, 7> tau_d_array{};
      Eigen::VectorXd::Map(&tau_d_array[0], 7) = tau_cmd;//将计算得到的 7 个关节的扭矩命令 tau_cmd 赋值给 tau_d_array 数组,
      return tau_d_array;
    };
    std::cout << "WARNING: Make sure sure that no endeffector is mounted and that the robot's last "
                 "joint is "
                 "in contact with a horizontal rigid surface before starting. Keep in mind that "
                 "collision thresholds are set to high values."
              << std::endl
              << "Press Enter to continue..." << std::endl;
    std::cin.ignore();
    // start real-time control loop
    robot.control(force_control_callback);

  } catch (const std::exception& ex) {
    // print exception
    std::cout << ex.what() << std::endl;
  }
  return 0;
}

 

标签:control,tau,Franka,force,Eigen,initial,state,array
From: https://www.cnblogs.com/ai-ldj/p/18294760

相关文章

  • Franka Robot 齐次变换矩阵 robot_state.O_T_EE
    O_T_EE 是一个4x4的齐次变换矩阵,用于描述末端执行器在机器人基座坐标系下的位置和姿态。这个矩阵的结构如下:[r11r12r13tx][r21r22r23ty][r31r32r33tz][0001]其中:r11到r33表示末端执行器的旋转矩阵tx、ty、tz表示末端执行器在机器人基座坐标系......
  • Franka Robot 多上位机控制控制方案
    Franka机器人来说,多个上位机可以同时对机器人进行控制,但需要遵循一些原则和注意事项:协作控制模式:多个上位机同时控制Franka机器人需要采用协作控制模式。在这种模式下,各个上位机向机器人发送的指令会被协调合并,避免指令冲突。访问权限管理:通常会对上位机的访问权限......
  • Franka Robot cmake demo
    cmake_minimum_required(VERSION3.4)#指定CMake的最低版本要求为3.4project(libfranka-examplesCXX)#定义项目名称为libfranka-examples,并指定语言为C++list(INSERTCMAKE_MODULE_PATH0${CMAKE_CURRENT_LIST_DIR}/../cmake)#将父目录的`cmake`子目录添加到......
  • Codeforces Round 954(Div. 3)
    CodeforcesRound954(Div.3)目录CodeforcesRound954(Div.3)\(C\).UpdateQueries\(D\).MathematicalProblem\(E\).BeautifulArray方法一:贪心+滑动窗口方法二:DP\(C\).UpdateQueries对索引数组\(ind\)去重排序对字符串\(c\)排序顺序遍历索引数组,将\(s[ind[i]......
  • Franka Robot 测试网络性能的示例(communication_test.cpp)
    //Copyright(c)2023FrankaRoboticsGmbH//UseofthissourcecodeisgovernedbytheApache-2.0license,seeLICENSE#include<chrono>#include<iostream>#include<thread>#include<franka/active_control.h>#include<frank......
  • Franka Robot setZeroForceTorque 设置零力矩
    在FrankaEmika机器人中,可以使用setZeroForceTorque()函数来设置机器人的零力矩。这个函数可以让机器人保持在零力矩状态,即不施加任何额外的力矩。这种状态下,机器人关节会保持"放松"的状态,可以被外力轻易地移动。以下是一个示例代码:#include<franka/robot.h>intmain()......
  • Franka Robot setDefaultBehavior的作用
    Franka机器人的setDefaultBehavior()函数是一个非常有用的功能,它可以设置机器人在遇到意外情况时的默认行为。这个函数可以帮助开发者更好地控制机器人的安全性和稳定性。以下是setDefaultBehavior()函数的一些常见用法:安全停止行为可以设置机器人在遇到紧急情况时(如检测......
  • Franka Robot robot.setJointImpedance()和robot.setCartesianImpedance()两个函数有
    robot.setJointImpedance()和robot.setCartesianImpedance()两个函数有以下区别和联系:区别:参考坐标系不同setJointImpedance()是设置每个关节的阻抗参数,以关节坐标系为参考。setCartesianImpedance()是设置机器人末端在笛卡尔空间中的阻抗参数,以笛卡尔坐标系为参考。......
  • Codeforces Round 916 (Div. 3)
    A.ProblemsolvingLog签到题,对于给出的字符串,记录每个字母出现的次数,然后遍历一遍,如果对应的字母出现的次数大于它的位次,则说明该题被解出来了,最后输出解题数量即可点击查看代码#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#......
  • 解决spring mvc设置controller切面无效
     maven的pem.xml配置<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.1.1.RELEASE</version></dependency><dependency&g......