当前位置: 首页 > news >正文

【完整】UR机械臂逆运动学求解过程及c++代码实现

有任何问题请在评论区留言,我尽可能的回复大家

一. 逆运动学的求解需要以下数学运算

  1. 利用DH参数得到每个关节的变换矩阵;
  2. 利用变换矩阵求出机械臂整个链的变换矩阵;
  3. 求出末端位姿;
  4. 利用已知末端位姿和整个链的变换矩阵,通过逆运动学方程来求解关节角度;
  5. 根据需求选解。

二. 代码实现过程

  1. 利用DH参数得到每个关节的变换矩阵:
Eigen::Matrix4d DH(double a, double d, double alpha, double theta) {Eigen::Matrix4d T;T << cos(theta), -sin(theta)*cos(alpha), sin(theta)*sin(alpha), a*cos(theta),sin(theta), cos(theta)*cos(alpha), -cos(theta)*sin(alpha), a*sin(theta),0, sin(alpha), cos(alpha), d,0, 0, 0, 1;return T;
}
  1. 利用变换矩阵求出机械臂整个链的变换矩阵:
Eigen::Matrix4d T_0e = Eigen::Matrix4d::Identity(4,4);
for (int i = 0; i < n; i++) {T_0e = T_0e * DH(a[i], d[i], alpha[i], theta[i]);
}
  1. 求出末端位姿:
Eigen::Matrix4d T_ee;
T_ee << 0.5938, -0.7381, 0.3254, 0.4494,0.8038, 0.5531, 0.2194, -0.1957,-0.0332, 0.3868, 0.9214, 0.6733,0, 0, 0, 1;
  1. 然后利用已知末端位姿和整个链的变换矩阵,通过逆运动学方程来求解关节角度。

三. 逆运动学方程求解关节角度

逆运动学方程求解关节角度是一个非线性方程组,有多种方法求解,如解析解、数值解等。这里以数值解的方法为例,介绍如何用c++代码实现逆运动学方程的求解。

  1. 实现齐次变换矩阵的逆变换:
Eigen::Matrix4d invT(const Eigen::Matrix4d& T) {Eigen::Matrix4d invT;invT.block<3,3>(0,0) = T.block<3,3>(0,0).transpose();invT.block<3,1>(0,3) = -invT.block<3,3>(0,0)*T.block<3,1>(0,3);invT.block<1,4>(3,0) << 0, 0, 0, 1;return invT;
}
  1. 实现逆运动学方程:
Eigen::Matrix<double,6,1> inverseKinematics(const Eigen::Matrix4d& T_ee, const Eigen::Matrix4d T_0e, const Eigen::Vector3d& p_e,const Eigen::Vector3d& o_x,const Eigen::Vector3d& o_y,const Eigen::Vector3d& o_z) {Eigen::Matrix<double,6,1> theta;Eigen::Matrix4d T_0e_inv = invT(T_0e);Eigen::Matrix4d T_ee_0 = T_ee * T_0e_inv;Eigen::Vector3d p_0 = T_ee_0.block<3,1>(0,3);Eigen::Vector3d o_z_0 = T_0e_inv.block<3,3>(0,0) * o_z;Eigen::Vector3d o_y_0 = T_0e_inv.block<3,3>(0,0) * o_y;Eigen::Vector3d o_x_0 = T_0e_inv.block<3,3>(0,0) * o_x;// 具体实现逆运动学方程,这里省略return theta;
}

其中逆运动学方程的计算的详细过程如下:
● 求解末端位置p和姿态R的关于机器人的参考坐标系的坐标。
● 根据UR10机械臂的末端位置和姿态,计算关节角度。
实现逆运动学方程的代码,它计算出的结果是一个长度为6的Eigen向量,代表6个关节的角度:

#include <Eigen/Dense>
#include <cmath>Eigen::Matrix<double, 6, 1> inverseKinematics(const Eigen::Matrix4d& T_ee, const Eigen::Matrix4d T_0e, const Eigen::Vector3d& p_e,const Eigen::Vector3d& o_x,const Eigen::Vector3d& o_y,const Eigen::Vector3d& o_z)
{Eigen::Matrix<double, 6, 1> joint_angles;Eigen::Vector3d p_0e = T_0e.block<3,3>(0,0).transpose() * (p_e - T_0e.col(3).head<3>());double c5 = T_ee(2,2);double s5 = sqrt(1 - c5*c5);joint_angles(4) = atan2(s5, c5);joint_angles(5) = atan2(-T_ee(0,2), T_ee(1,2));joint_angles(3) = atan2(T_ee(2,1)/s5, T_ee(2,0)/s5);double s3 = sin(joint_angles(3));double c3 = cos(joint_angles(3));joint_angles(0) = atan2((p_0e(1)*s3 - p_0e(2)*c3) / s5, p_0e(0) - (p_0e(1)*c3 + p_0e(2)*s3) * c5);joint_angles(2) = atan2((p_0e(1)*c3 + p_0e(2)*s3) / c5, p_0e(0) - p_0e(1)*s3 + p_0e(2)*c3);joint_angles(1) = atan2(o_y(0), o_x(0));return joint_angles;
}

根据这个计算流程,将步骤 2 中省略的逆运动学方程具体实现的代码补充上:

Eigen::Matrix<double,6,1> inverseKinematics(const Eigen::Matrix4d& T_ee, const Eigen::Matrix4d T_0e, const Eigen::Vector3d& p_e,const Eigen::Vector3d& o_x,const Eigen::Vector3d& o_y,const Eigen::Vector3d& o_z) {Eigen::Matrix<double,6,1> theta;Eigen::Matrix4d T_0e_inv = invT(T_0e);Eigen::Matrix4d T_ee_0 = T_ee * T_0e_inv;Eigen::Vector3d p_0 = T_ee_0.block<3,1>(0,3);Eigen::Vector3d o_z_0 = T_0e_inv.block<3,3>(0,0) * o_z;Eigen::Vector3d o_y_0 = T_0e_inv.block<3,3>(0,0) * o_y;Eigen::Vector3d o_x_0 = T_0e_inv.block<3,3>(0,0) * o_x;
// 逆运动学方程的具体实现double q1, q2, q3, q4, q5, q6;double d = p_e(2) - p_0(2);q1 = atan2(p_0(1), p_0(0));double c2 = (pow(p_0(0), 2) + pow(p_0(1), 2) - pow(d, 2) - pow(o_x_0(2), 2)) / (2 * o_x_0(2) * sqrt(pow(p_0(0), 2) + pow(p_0(1), 2) - pow(d, 2)));q2 = atan2(sqrt(1-pow(c2, 2)), c2);q3 = atan2(o_z_0(2), -o_x_0(0) * sin(q2) + o_x_0(2) * cos(q2));double s4 = -o_y_0(2) * cos(q2) - o_y_0(0) * sin(q2) * sin(q3) + o_y_0(1) * sin(q2) * cos(q3);double c4 = o_x_0(0) * cos(q3) + o_x_0(1) * sin(q3) + o_x_0(2) * sin(q2);q4 = atan2(s4, c4);double s5 = o_x_0(0) * cos(q3) * sin(q4) + o_x_0(1) * sin(q3) * sin(q4) + o_x_0(2) * cos(q4);double c5 = o_y_0(0) * cos(q3) * cos(q4) + o_y_0(1) * sin(q3) * cos(q4) - o_y_0(2) * sin(q4);q5 = atan2(-s5, c5);double s6 = -o_x_0(0) * sin(q3) + o_x_0(1) * cos(q3);double c6 = o_y_0(0) * cos(q3) * cos(q5) + o_y_0(1) * sin(q3) * cos(q5) - o_y_0(2) * sin(q5);q6 = atan2(s6, c6);theta << q1, q2, q3, q4, q5, q6;return theta;
}  

上面代码中的逆运动学方程的返回值 theta 可能会有多组解(UR机械臂通常为8组解),但是通常情况下仅返回一组最合适的解,因为它对应的正运动学方程只能够求出一组解。如果机器人的关节范围限制了某些解的取值范围,则需要在代码中加入关节范围限制的判断,以保证返回的解在关节范围内。
在当前代码中并没有对多组解进行选取的部分,所以该代码中直接返回的是求得的一组解。因为选取某一组解的方式取决于你所实现的逆运动学算法以及实际的应用需求,对于不同的需求,还需要对代码进行进一步的修改以实现选取一组合法的解的功能。
对于选解我在这里举一个例子:机械臂六个关节角度均有最大和最小的限制。
那么选解的代码可以写为:

if (q1 < q1_min) {q1 = q1 + 2 * M_PI;}if (q1 > q1_max) {q1 = q1 - 2 * M_PI;}// 根据需求,确定q2的取值范围if (q2 < q2_min) {q2 = q2_min;}if (q2 > q2_max) {q2 = q2_max;}// 根据需求,确定q3的取值范围if (q3 < q3_min) {q3 = q3_min;}if (q3 > q3_max) {q3 = q3_max;}// 根据需求,确定q4的取值范围if (q4 < q4_min) {q4 = q4_min;}if (q4 > q4_max) {q4 = q4_max;}// 根据需求,确定q5的取值范围if (q5 < q5_min) {q5 = q5_min;}if (q5 > q5_max) {q5 = q5_max;}// 根据需求,确定q6的取值范围if (q6 < q6_min) {q6 = q6_min;}if (q6 > q6_max) {q6 = q6_max;}theta << q1, q2, q3, q4, q5, q6;return theta;

相关文章:

【完整】UR机械臂逆运动学求解过程及c++代码实现

有任何问题请在评论区留言&#xff0c;我尽可能的回复大家 一. 逆运动学的求解需要以下数学运算 利用DH参数得到每个关节的变换矩阵&#xff1b;利用变换矩阵求出机械臂整个链的变换矩阵&#xff1b;求出末端位姿&#xff1b;利用已知末端位姿和整个链的变换矩阵&#xff0c;…...

68. Python的相对路径

68. Python的相对路径 文章目录68. Python的相对路径1. 知识回顾2. 什么是相对路径3. 相对路径的语法4. 查看相对路径的方法5. 写出所有txt文件的相对路径5.1 同目录5.2 上级目录6. 用相对路径读取txt文件6.1 读取旅游.txt6.2 读取旅游经费.txt6.3 读取笔记.txt和new.txt6.4 读…...

java数据类型

数据类型 类型分类&#xff0c;存储范围&#xff0c;字面量&#xff0c;默认值&#xff0c;类型转换 类型分类 存储范围 数据类型字节数表示范围byte1-128~127short2-32768~32767&#xff0c;正负3万左右int4-2147483648~2147483647&#xff0c;正负21亿左右long8-922337203…...

Kotlin 替换非空断言的几种方式

Kotlin 出现断言的两种情形 IDE java 与 kotlin 自动转换时&#xff0c;自动添加非空断言的代码Smart Cast 失效 代码展示&#xff1a; class JavaConvertExample {private var name: String? nullfun init() {name ""}fun foo() {name null;}fun test() {if (…...

2023年了,来试试前端格式化工具

在大前端时代&#xff0c;前端的各种工具链穷出不断&#xff0c;有eslint, prettier, husky, commitlint 等, 东西太多有的时候也是trouble&#x1f602;&#x1f602;&#x1f602;,怎么正确的使用这个是每一个前端开发者都需要掌握的内容&#xff0c;请上车&#x1f697;&…...

spring cloud 企业工程项目管理系统源码+项目模块功能清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…...

TCP分片解析

本文目录什么是IP分片为什么会产生IP分片为什么要避免IP分片如何避免IP分片什么是IP分片 IP协议栈将TCP/UDP传输层要求它发送的&#xff0c;但长度大于发送端口MTU的一个数据包&#xff0c;分割成多个IP报文后分多次发送。这些分成多次发送的多个IP报文就是IP分片。 为什么会…...

开发了一款基于 Flask 框架的在线电影网站系统(附 Python 源码)

文章目录前言项目介绍源码获取运行环境安装依赖库项目截图首页展示图视频展示页视频播放页后台管理页整体架构设计图项目目录结构图前台功能模块图后台功能模块图本地运行图前言 今天我给大家分享的是基于 Python 的 Flask 框架开发的在线电影网站系统&#xff0c;大家平时需要…...

如何获得CSM--敏捷教练证书

1、什么是CSM&#xff1f;CSM即Certified Scrum Master,Scrum Master负责确保所有人都能正确地理解并实施Scrum&#xff0c;确保Scrum团队遵循Scrum的理论、实践和规则。Scrum Master是Scrum团队中的服务型领导&#xff0c;帮助Scrum团队外的人员了解他们如何与Scrum团队交互是…...

Java面试数据库

目录 一、关系型数据库 数据库权限 表设计及创建 表数据相关 数据库架构优化 二、非关系型数据库 redis 今天给大家稍微整理了一下&#xff0c;内容有数据表设计的三大范式原则、sql查询如何优化、redis数据的击穿、穿透、雪崩等...&#xff0c;以及相关的面试题&#xff0…...

关于进行vue-cli过程中的解决错误的问题

好久没发文章了&#xff0c;直到今天终于开始更新了&#xff0c;最近想进军全端&#xff0c;准备学习下vue&#xff0c;但是这东西真的太难了&#xff0c;我用了一天的时间来解决在配置中遇到的问题&#xff01;主要问题&#xff1a;cnpm文件夹和vue-cli文件夹的位置不对并且vu…...

Rockchip Linux USB Gadget

一:概述 USB Gadget 是运行在 USB Peripheral 上配置 USB 功能的子系统,正常可被枚举的 USB 设备至少有 3 层逻辑层,有些功能还会在用户空间多跑一层逻辑代码。Gadget API 就是具体功能和硬件底层交互的中间层。从上到下,逻辑层分布为: USB Controller: USB上最底层的软…...

Linux -文件系统操作与帮助命令

1、Linux -文件系统操作 df — 查看磁盘的容量 df -h —以人类可以看懂的方式显示磁盘的容量&#xff0c;易读 du 命令查看目录的容量 # 默认同样以块的大小展示 du # 加上 -h 参数&#xff0c;以更易读的方式展示 du -h-d 参数指定查看目录的深度&#xff1a; # 只查看 1…...

UMI 创建react目录介绍及配置

UMI 生成react项目目录介绍及配置 react项目目录介绍umi多种配置方案运行时配置app.ts 的使用 1、umi创建的项目目录大致如下 ├─package.json 配置依赖以及启动打包所需的命令 ├─.umirc.ts 配置文件&#xff0c;包含 umi 内置功能和插件的配置 ├── dist 打包后生成的…...

基于matlab使用机器学习和深度学习进行雷达目标分类

一、前言此示例展示了如何使用机器学习和深度学习方法对雷达回波进行分类。机器学习方法使用小波散射特征提取与支持向量机相结合。此外&#xff0c;还说明了两种深度学习方法&#xff1a;使用SqueezeNet的迁移学习和长短期记忆&#xff08;LSTM&#xff09;递归神经网络。请注…...

Protocol Buffers V3语法全解

目录protobuf介绍protobuf使用protoc命令语法定义消息类型指定字段类型分配字段编号指定字段规则添加更多消息类型注释保留字段从.proto文件生成了什么&#xff1f;值类型默认值枚举使用其他消息类型导入定义嵌套类型更新消息类型未知字段any任意类型oneofoneof 特性兼容性问题…...

MediaPipe之人体关键点检测>>>BlazePose论文精度

BlazePose: On-device Real-time Body Pose tracking BlazePose&#xff1a;设备上实时人体姿态跟踪 论文地址&#xff1a;[2006.10204] BlazePose: On-device Real-time Body Pose tracking (arxiv.org) 主要贡献: &#xff08;1&#xff09;提出一个新颖的身体姿态跟踪解决…...

CSS从入门到精通专栏简介

先让我们来欣赏几个精美的网站&#xff1a; Matt Brett - Freelance Web Designer and WordPress Expert ‎2022 Year in Review • Letterboxd NIO蔚来汽车官方网站 小米官网 Silk – Interactive Generative Art 大屏数据可视化 你是否也有过这样的“烦恼”&#xff1a; * …...

day01常用DOS命令

day01课堂笔记&#xff08;第一章 Java开发环境的搭建&#xff09; 1、常用的DOS命令 1.1、怎么打开DOS命令窗口 win键 r &#xff08;组合键&#xff09;&#xff1a;可以打开“运行”窗口 在运行窗口文本框中输入: cmd 然后回车 1.2、什么是DOS命令呢&#xff1f; 在DOS命令…...

Java设计模式-生成器模式(建造模式)

1.1定义 维基百科定义 生成器模式&#xff08;英&#xff1a;Builder Pattern&#xff09;是一种设计模式&#xff0c;又名&#xff1a;建造模式&#xff0c;是一种对象构建模式。 它可以将复杂对象的建造过程抽象出来&#xff08;抽象类别&#xff09;&#xff0c;使这个抽象…...

ansible的常用模块介绍

ansible 常用命令/usr/bin/ansible  #Ansibe AD-Hoc 临时命令执行工具&#xff0c;常用于临时命令的执行/usr/bin/ansible-doc #Ansible 模块功能查看工具/usr/bin/ansible-galaxy  #下载/上传优秀代码或Roles模块 的官网平台&#xff0c;基于网络的/usr/bin/ansible-playbo…...

你不会还不知道如何监测用户的网络是否在线吧?

我最近遇到一个需求&#xff0c;要给网站添加一个用户网络离线提醒。要求我们要实时监测用户的网络状态&#xff0c;当用户断网了&#xff0c;我们要立马给用户弹出一个断网提醒。 那你可能会问&#xff0c;为什么要做这么一个需求呢&#xff1f;用户断网了&#xff0c;网页不…...

ASM Quorum FailGroup RAC on Extended Distance Clusters

法定容错组&#xff0c;和它失去联系也不影响集群运行 参考&#xff1a; How to Manually Add NFS voting disk to an Extended Cluster using ASM in 11.2 (Doc ID 1421588.1) Mount Options for Oracle files when used with NFS on NAS devices (Doc ID 359515.1) RAC: Fre…...

VHDL语言基础-时序逻辑电路-触发器

目录 触发器&#xff1a; D触发器&#xff1a; 触发器的VHDL描述&#xff1a; 触发器的仿真波形如下&#xff1a;​编辑 时钟边沿检测的三种方法&#xff1a; 方法一: 方法二&#xff1a; 方法三&#xff1a; 带有Q非的D触发器&#xff1a; 带有Q非的D触发器的描述&am…...

也许你应该学学 postman了

使用 最简单的方法就是直接在浏览器中复制 Copy as cURL &#xff0c;然后把数据导入 postman&#xff0c;然后 send &#xff0c;收工。 我们这里拿 知乎首页 举例 在对应的请求下复制 cURL 打开 postman &#xff0c; 点击左上角的 Import &#xff0c; 选择Paste Raw Tex…...

VHDL语言基础-状态机设计-ASM图法状态机设计

目录 有限状态机的描述方法&#xff1a; ASM图&#xff1a; 状态转移图&#xff1a; 状态转移列表&#xff1a; MDS图&#xff1a; ASM图法状态机设计&#xff1a; ASM图的组成&#xff1a; 状态框&#xff1a; 判断框&#xff1a; 条件框&#xff1a; 状态框与条件框…...

Python文件的属性获取,重命名,目录的创建,显示和改变

1. 文件的属性获取 os.stat()函数可以获取文件的属性&#xff0c;该函数会返回一个和系统平台有关的stat_result对象&#xff0c; 具备一组可访问的属性&#xff0c;可以通过 stat_result.attribute 这样的格式来访问各个属性的值。 字 段描 述st_modeinode 保护模式st_inoin…...

好用的iPhone 数据恢复软件精选

随着 Apple 的 iTunes / iCloud 备份服务的兴起&#xff0c;我们总是假设这些信息在我们需要的时候可以随时访问。然而&#xff0c;事实是&#xff0c;意想不到的“不幸”发生了&#xff0c;比如 iOS 升级失败、忘记密码&#xff0c;或者更严重的情况&#xff0c;如进水或被盗。…...

Linux搭建redis集群6.x版本【超简单】

Linux搭建redis集群6.x版本【超简单】&#xff1a;&#xff1a;&#xff1a;&#xff1a;本文主要展示如何在一台服务器上搭建集群&#xff0c;核心思想就是复制实例&#xff0c;修改启动端口&#xff0c;实际上跟在几台服务器的操作都是一样的。一.安装redis wget http://dow…...

双重检查锁是如何避免缓存雪崩的,代码例子说明

双重检查锁是如何避免缓存雪崩的什么是缓存雪崩解决方案双重检查锁是如何工作的什么是缓存雪崩 缓存雪崩是指缓存同时失效&#xff0c;造成大量的缓存请求都请求到后端数据库&#xff0c;导致后端系统压力过大而瘫痪的情况。 解决方案 设置缓存的失效时间为随机值&#xff0…...

邢台网站建设服务周到/凡科建站

【2018.02】劳特利奇国防研究手册&#xff08;第一版&#xff09;Routledge Handbook of Defence Studies&#xff0c;共412页。 如果需要电子版&#xff0c;请联系QQ&#xff1a;3042075372。 Routledge是英国的一家跨国出版社&#xff0c;总部设在伦敦&#xff0c;主要在伦敦…...

用java做网站教程/烟台seo外包

Android:自定义View&#xff08;一&#xff09; 自定义View&#xff1a; 就是继承系统的View&#xff0c;通过添加绘制元素&#xff0c;逻辑以实现自己想要实习的效果的控件。在Android开发过程中&#xff0c;我们想要的效果大多数情况下可以直接使用系统提供的控件来实现&…...

wordpress内网oss/seo搜索引擎优化实战

2019独角兽企业重金招聘Python工程师标准>>> 算法很简单 如果你不明白&#xff0c;找一堆台球和两个杯子&#xff0c;想想怎么把球按照放的顺序取出来就行了。 整存整取思想package queueimport java.util.*fun main(args: Array<String>) {var twoStackQueue…...

学校网站的建设费用/百度开户代理

许多外贸公司在选择邮箱时&#xff0c;单次群发量和邮箱容量都是客户选择邮箱品牌的必要条件。小编了解到一些做外贸的公司是需要跟海外的客户发邮件业务往来的&#xff0c;所以&#xff0c;他们需要单次群发量非常高&#xff0c;目前小编了解到&#xff0c;还有一些外贸公司的…...

没有备案的网站怎么访问/网站推广优化排名教程

熔断 当某个服务调用慢或者有大量超时现象(过载)&#xff0c;系统停止后续针对该服务的调用而直接返回&#xff0c;直至情况好转才恢复调用。这通常是为防止造成整个系统故障而采取的一种保护措施&#xff0c;也称过载保护。很多时候刚开始&#xff0c;可能只是出现了局部小规…...

plc编程培训机构/搜索引擎优化培训

PS: 1.form2是主窗体&#xff0c;form1是子窗体&#xff0c;我当时安装的是XE8&#xff0c;新建第一个窗体就是叫form2。 2.事件处理用到了控件&#xff08;ApplicationEvents1&#xff09;。 3.源代码下载地址&#xff1a;“https://download.csdn.net/download/zhujianqiangq…...