CSARA机械手正反解代码解读和左右手定则应用

前言:前段时间在某鱼上买了一份CSARA的机械臂的程序,拿出来分享一下,并记录一下。说明一下并非是公司的核心代码,我也不搞这个....侵权就删了。

首先简单回顾一下CSARA的正逆解。

根据几何的方法能求出末端在平面坐标系中的xy坐标。也就是正解。知道了各个关节的角度,求末端的位置。 一般的思路是这样的,但是有一个左右手定则的方式,也就是可以建立不同的坐标系。左右手定则,一般使用在还有摄像头的一个情况,摄像头进行识别的情况。

比如你建立的坐标系刚好是右手定则,而摄像头看物体就是符合左手定则,所以会有左右手坐标转换。如图

我们假设机器关节的theta2角度在右手定则是大于180度的,比如280度,而在左手定则中却是360-270 = 80的,进而对其转换成统一坐标系的。

左右手定则公式:

推理是很简单的,仅仅用到了三角函数和三角形求角度的通用公式。注意一点哈,左右手的主要目的是对其坐标系的转换。左->右或者右->左。

写成代码则是:

 看的出来,实际上主要还是a的不同,通过a来进行转换的。

好了,左右手的用法已经知道了,相信利用几何法也能够进行出正逆解的公式。大家可以自行推导,这片文章的重点并不在这里。

主代码:


int main()
{ScaraLib scara;scara.createUserCrd(cv::Point2f(100,100),90.0/180.0*CV_PI);cv::Point2f rp1(100*sqrt(2), 0);cv::Point2f cp2;scara.cvtRobotUserCrd(rp1, cp2);double atn = atan2(1, 2);//反解scara.setXYZC(34, 22, 0, 0.56);double j1, j2, j3, j4;scara.getJn(j1, j2, j3, j4);double x, y, z, c;//正解scara.setJn(j1, j2, j3, j4);scara.getXYZC(x, y, z, c);//反解scara.setXYZC(x, y, z, c);scara.getJn(j1, j2, j3, j4);//验证正逆解std::vector<cv::Point2f> camera;std::vector<cv::Point2f> robot;camera.push_back(cv::Point2f(10, 10));camera.push_back(cv::Point2f(10, 100));camera.push_back(cv::Point2f(100, 100));camera.push_back(cv::Point2f(100, 10));robot.push_back(cv::Point2f(10, 10));robot.push_back(cv::Point2f(10, 100));robot.push_back(cv::Point2f(100, 100));robot.push_back(cv::Point2f(100, 10));scara.createUserCrd(camera, robot);cv::Point2f p1 = cv::Point2f(10, 10);   //相机坐标系cv::Point2f p2;                        //基坐标系scara.setUserXYZC(34, 22, 0, 0.56);scara.getUserXYZC(x, y, z, c);return 0;
}

一步步来,慢慢分析,第一句话scara.createUserCrd(cv::Point2f(100,100),90.0/180.0*CV_PI);的意思是用一个点+角度来创建用户坐标系。


//用一个点+一个角度创建用户坐标系统
bool ScaraLib::createUserCrd(const cv::Point2f& tnHome, double angle)
{double rd = 1000;cv::Point2f rp1(0, 0);cv::Point2f rp2(rd, 0);cv::Point2f rp3(0, rd);cv::Point2f cp1(tnHome.x, tnHome.y);cv::Point2f cp2(tnHome.x + rd*cos(angle), tnHome.y + rd*sin(angle));cv::Point2f cp3(tnHome.x + rd*cos(angle + CV_PI / 2.0), tnHome.y + rd*sin(angle + CV_PI / 2.0));std::vector<cv::Point2f> camera;std::vector<cv::Point2f> robot;camera.push_back(cp1); robot.push_back(rp1);camera.push_back(cp2); robot.push_back(rp2);camera.push_back(cp3); robot.push_back(rp3);return createUserCrd(camera, robot);
}

其实也很好理解,cp1是用户坐标系(摄像头坐标系),rp1是机器人本身的坐标系。先解释一波在看图,我们把rp1和cp1看做坐标系原点位置,rp2和cp2看做x方向的位置,rp3和cp3看做y方向的位置。好了是不是有点明白了。看图,输入是(cv::Point2f(100,100),90.0/180.0*CV_PI这个是openCV 读取出的数据,而最终返回的是camera和robot,但是接下来还内嵌了一个createUserCrd函数。

//创建用户坐标系统
bool ScaraLib::createUserCrd(const std::vector<cv::Point2f>& camera, const std::vector<cv::Point2f>& robot)
{mCamera = camera;mRobot = robot;//当数据只有两个点时,需要补充一个点cv::Point2f cpt_c;cv::Point2f rpt_c;rotate(camera[1], camera[0], CV_PI / 2.0, cpt_c);rotate(robot[1], robot[0], CV_PI / 2.0, rpt_c);mCamera.push_back(cpt_c);mRobot.push_back(rpt_c);return true;
}

这里的思路是把用户自己建立的坐标系转换成机器人坐标系,解释一下:camera和robot分别是(3个点都已知了):

(数据为假设的,目的是明白camera的存储方式),这里有一个c++的函数重载用法,也就是同一个函数名字,不同输入参数,编译器会根据不同的输入参数进行识别函数体,进行运行,如下:

嗯。。最后的这个输入5个参数的rotate函数,是一个二维旋转变换的公式,即,可以理解绕z轴进行旋转。之后利用mCamera.push_back(cpt_c);这个函数放在mCamera后面,即现在就是0,0 1,0 0,1 1,1了。但是哈,查找了整个程序,没有发现其他地方使用mCamera函数,不太理解,有理解的可以一起说说。啊我猜测哈,这里是只有两个点的情况下,生成第3个点的情况,但是根据opencv来说给到了3个点,所以就是没有使用。

 

好了,这个先不重要,继续来看。这里才是创建用户坐标系统的重点,换一句话说就是设定的坐标系相当于基坐标系的旋转变换。

    mUserCrd_1 = createMarkN(camera, robot);mUserCrd_2 = createMarkN(robot, camera);cv::Point2f p1 = cv::Point2f(1000, 1000);cv::Point2f p2; //默认为0,0cvtUserRobotCrd(p1, p2);double angle1 = atan2(p1.y, p1.x);double angle2 = atan2(p2.y, p2.x);double angle3 = angle2 - angle1;mUserRobotAngle_Rz = angle3;double rx1 = atan2(0, p1.y);double rx2 = atan2(0, p2.y);mUserRobotAngle_Rx = rx2 - rx1;

 最主要的还是上面的这个,这个说白了就是在求刚性(齐次)变换矩阵和旋转角,createMarkN是根据opencv里面的刚性变换矩阵函数estimateRigidTransform求出刚性变换矩阵,求出ABCDEF。

之后利用矩阵相乘的关系,求出用户坐标推换到机器人坐标。换一句话说就是把这个点在用户坐标系推到为机器人坐标系中。

其中点在用户坐标是1000,1000, mUserCrd_1是否销毁用户坐标系,p2是点在机器人坐标系中的坐标。

而知道了p1在用户坐标系下的坐标(摄像头),p2在机器人下的坐标(基坐标系,公式推到而来),那么计算这两个坐标系之间的旋转角度为:

	double angle1 = atan2(p1.y, p1.x);double angle2 = atan2(p2.y, p2.x);double angle3 = angle2 - angle1;mUserRobotAngle_Rz = angle3;

 angle3 是点 p2 相对于点 p1 的旋转角度,注意可以看做是绕z轴进行旋转的,这一点很重要,不管是前面的左右手定则,还是坐标系的建立和他们之间的联系,都要时刻牢记这一点。应该很好理解。同理可证,后面的那个是对于x轴方向上的旋转角度。

好了,饶了上面这么一个大圈子,最终得到了用户坐标系上的点在机器坐标系下的点。那么可以做到的一件事是:摄像头捕捉到的点,可以转换到机器人坐标系下,那么这个转换为机器人坐标下的就可以说是机器人末端的位置。

理解了上面的内容,接下来再回到主函数。

将机器人坐标系中的点 rp1 转换到用户坐标系中的点 cp2,并计算一个角度 atn。

这一步是用来验证正逆解是否正确的,逆解得到的关节角度,赋值给正解,看最后末端末端位置姿态是否和给定的一致。 此时后面的和前面分析是一样的。

好了。以上就是主函数的全部内容了,其实代码中还有一些直线和圆弧差补,以后再分析(主要看有没有人想看,想看就拿出来分享一下)

可以简单说一下:直线差补有很多种方式,此次程序就是最简单的方式,是deta的方式,计算出斜率和截距来,进行推算下一个位置点的坐标,这种方法不是说不好,有一个缺点就是不能够很丝滑的运行从初始点到终止点。还有一种就是利用一个定时周期的方法,利用速度和点的位置来计算,在使用其他的方法进行优化,这一方法不但大大减小了不够丝滑的运行,还解决可以进行高速运行。

每日一感悟:遗憾是什么?是初见少年拉满弓,不惧岁月不惧风。可终是东风吹醒英雄梦,生活磨平少年心。原以为山一程,水一程,人生何处不相逢,可后来才发现,一别再无归期,相见只在梦里,是这样吗?世事难两全,得失总相伴。

或许遗憾才是常态,不完美才是人生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1536767.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

第二百三十五节 JPA教程 - JPA Lob列示例

JPA教程 - JPA Lob列示例 以下代码显示了如何使用Lob注释将字节数组保存到数据库。 LOB在数据库中有两种类型&#xff1a;字符大对象&#xff08;称为CLOB&#xff09;和二进制大对象&#xff08;或BLOB&#xff09;。 CLOB列保存大字符序列&#xff0c;BLOB列可存储大字节序…

Linux memcg lru lock提升锁性能

内核关于per memcg lru lock的重要提交&#xff1a; f9b1038ebccad354256cf84749cbc321b5347497 6168d0da2b479ce25a4647de194045de1bdd1f1d 计算虚拟地址转换基本机制 为了处理多应用程序的地址冲突&#xff0c; linux 系统在应用中使用了虚拟地址&#xff0c;得益于硬件的…

SpringBoot+vue集成sm国密加密解密

文章目录 前言认识SM2后端工具类实现引入依赖代码实现工具类&#xff1a;SM2Util 单元测试案例1&#xff1a;生成服务端公钥、私钥&#xff0c;前端js公钥、私钥案例2&#xff1a;客户端加密&#xff0c;服务端完成解密案例3&#xff1a;服务端进行加密&#xff08;可用于后面前…

禹神:一小时彻底搞懂跨域解决方案

1. 浏览器的同源策略 2. 跨域会受到哪些限制 4. CORS 解决 Ajax 跨域问题 exposedHeaders 不加这个&#xff0c;js拿不到这个响应头(浏览器控制台network中能看见&#xff0c;但是js拿不到) 5. JSONP 解决跨域问题 JSOP只能解决get请求 服务端代码 客户端代码 服务端代码升…

卡尔曼滤波中Q和R与噪声的关系

卡尔曼滤波 一种用于估计系统状态的递归滤波器&#xff0c;通过融合传感器测量和系统模型&#xff0c;提供系统状态的最优估计。 Q和R是什么 在卡尔曼滤波中&#xff0c;Q和R分别表示过程噪声和测量噪声的协方差矩阵。 Q Q Q矩阵&#xff08;过程噪声协方差矩阵&#xff09;…

LC并联电路在正弦稳态下的传递函数推导(LC并联谐振选频电路)

LC并联电路在正弦稳态下的传递函数推导&#xff08;LC并联谐振选频电路&#xff09; 本文通过 1.解微分方程、2.阻抗模型两种方法推导 LC 并联选频电路在正弦稳态条件下的传递函数&#xff0c;并通过仿真验证不同频率时 vo(t) 与 vi(t) 的幅值相角的关系。 电路介绍 已知条件…

人工智能和大模型的简介

文章目录 前言一、大模型简介二、大模型主要功能1、自然语言理解和生成2、文本总结和翻译3、文本分类和信息检索4、多模态处理三、大模型的技术特性1、深度学习架构2、大规模预训练3、自适应能力前言 随着技术的进步,人工智能(Artificial Intelligence, AI)和机器学习(Mac…

建设世界一流财务管理体系【数字化顶层设计】【持续更新】

财务管理是企业管理的中心环节&#xff0c;是企业实现基业长青的重要基础和保障。近年来&#xff0c;中央企业认真贯彻落实党中央、国务院决策部署&#xff0c;高度重视财务管理工作&#xff0c;持续优化管理手段&#xff0c;不断创新管理模式&#xff0c;积极应用先进管理工具…

CSS调整背景

一、设置背景颜色 通过 background-color 属性指定&#xff0c;值可以是十六进制 #ffffff&#xff0c;也可以是rgb(0, 255, 255)&#xff0c;或是颜色名称 "red" div {background-color: red; /* 通过颜色名称设置 */background-color: #ff0000; /* 通过十六进制设…

面向对象程序设计之继承(C++)

1.继承的定义 1.1继承的概念 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段&#xff0c;它允许我们在保持原有类特性的基础上进⾏扩展&#xff0c;增加⽅法(成员函数)和属性(成员变量)&#xff0c;这样产⽣新的类&#xff0c;称派⽣类。继承 呈现了⾯向…

给虚拟机linux系统安装交叉编译工具链

我们在电脑上写的代码编译生成的是X86架构的二进制文件&#xff0c;只能在X86平台上运行&#xff0c;而开发板是ARM架构因此需要安装交叉编译链工具&#xff0c;这样在电脑上写的代码交叉编译之后生成的是ARM架构的二进制文件。 绿色的字眼是与本文无关的只是这样有助于我们的…

推荐5款AI论文大纲生成器,一键极速生成!

在当今学术研究和写作领域&#xff0c;AI论文大纲生成器的出现极大地提高了写作效率和质量。以下是五款功能强大且全面的AI论文大纲生成器推荐&#xff1a; 一、千笔-AIPassPaper 千笔-AIPassPaper是一款基于深度学习和自然语言处理技术的AI写作助手&#xff0c;旨在帮助用户…

【探索数据结构与算法】希尔排序原理、实现与分析(图文详解)

目录 一、 引言 二、算法思想 三、算法步骤 四、代码实现 五、复杂度 &#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;探索数据结构与算法 一、 引言 希尔排序&#xff08;Shell Sort&#xff09;是插入排序的一种更高效的改进版本&#x…

【Kubernetes笔记】为什么DNS解析会超时?

【Kubernetes笔记】为什么DNS解析会超时&#xff1f; 目录 1 问题背景2 产生后续的问题3 DNS 负缓存工作原理&#xff1a;4 如何解决和缓解 DNS 负缓存 4.1 减小负缓存 TTL4.2 重试机制4.3 减少 Pod 的频繁重启或调度4.4 使用 Headless Service4.5 手动刷新 DNS 缓存 5 总结 …

【电脑组装】✈️从配置拼装到安装系统组装自己的台式电脑

目录 &#x1f378;前言 &#x1f37b;一、台式电脑基本组成 &#x1f37a;二、组装 &#x1f379;三、安装系统 &#x1f44b;四、系统设置 &#x1f440;五、章末 &#x1f378;前言 小伙伴们大家好&#xff0c;上篇文章分享了在平时开发的时候遇到的一种项目整合情况&…

15. 三数之和(实际是双指针类型的题目)

15. 三数之和 15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以…

支持升降压型、升压、降压、60V的1.2MHz频率LED恒流驱动器LGS63040、LGS63042

前言&#xff1a; 一款支持升降压的LED驱动器。适合单节锂电池使用。当然不仅于此。SOT23-5封装的外形和丝印 特性 宽输入电压、宽输出电压范围&#xff1a;3.0V-60V 支持 PWM 调光及模拟调光 内置 60V/350mΩ低侧金属氧化物半导体场效应晶体管 1.2MHz固定工作频率 逐周期峰值…

面试官问:你在团队中的角色是什么?

面试官问你在团队中的角色是什么&#xff0c;其目的是了解你如何在团队环境中工作&#xff0c;以及你如何看待自己在团队中的定位。他们希望听到你如何与他人协作、你的领导能力或团队合作精神&#xff0c;以及你是否能适应不同的团队角色。 回答这类问题时&#xff0c;你可以…

(南京观海微电子)——GH7006+Boe_6.8_AV068WVU-N10原理介绍

​​​​​​​​​​​​​​​​​​​​​​​​​​​​

07_Python数据类型_集合

Python的基础数据类型 数值类型&#xff1a;整数、浮点数、复数、布尔字符串容器类型&#xff1a;列表、元祖、字典、集合 集合 集合&#xff08;set&#xff09;是Python中一个非常强大的数据类型&#xff0c;它存储的是一组无序且不重复的元素&#xff0c;集合中的元素必须…