机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节)
机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节)
- 1、前言
- 2、本篇内容
- 3、代码记录
- 3.1、新建se2
- 3.2、生成坐标系
- 3.3、将T1表示的变换绘制
- 3.4、完整绘制代码
- 3.5、获取点`*`在坐标系1下的表示
- 3.6、相对坐标获取完整代码
- 4、结语
1、前言
工作需要,想同时显示出六轴协作臂,一组位姿信息逆解出的八组关节角的效果情况。就想使用MATLAB的机器人工具箱RTB去实现这一需求,辅助数据分析。朋友推荐了《机器人学、机器视觉与控制》这本书,书的作者也是工具箱RTB的作者,就开始拜读补充基础知识,并结合书中的RTB示例代码熟悉RTB的使用。个人使用的matlab2022b版本和10.4版本的RTB,实际操作时发现书本中的示例代码(猜测应该是9版本的RTB,语法未做到向下兼容)在个人使用的环境下,频繁出现报错无法运行的问题。就准备写一个改正后的实机运行记录系列。
2、本篇内容
记录书中第2.1章节中的示例代码,修改后能在10.4版本中正确运行。
3、代码记录
3.1、新建se2
原书中的第一步是用函数se2创建一个齐次变换,原书代码如下:
>> T1 = se2(1, 2, 30 * pi / 180)
T1 = 0.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000
在高位版本环境
下,运行报错,原因是se2
的函数形参变动调整了
>> T1 = se2(1, 2, 30 * pi / 180)
错误使用 matlabshared.spatialmath.internal.SE2Base
Invalid number of arguments. To create an se2, specify 2 or fewer arguments.出错 se2 (第 69 行)obj@matlabshared.spatialmath.internal.SE2Base(varargin{:});
下面我们来看看help文档中,高版本的se2
函数定义:
原书中是位移在前,旋转在后,高版本恰恰相反了。因此,新建se2
需要修改为(可能步骤有些繁琐,欢迎评论区留言优化):
>> tr = [1, 2]tr =1 2
>> rot = rotz(30)rot =0.8660 -0.5000 00.5000 0.8660 00 0 1.0000>> T1 = se2(rot(1:2, 1:2), tr)T1 = se20.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000
3.2、生成坐标系
这个没有问题,同原书一样即可,生成一个XY轴分别为[0,5]刻度的二维平面坐标系。
>> axis([0 5 0 5]);
3.3、将T1表示的变换绘制
原书代码如下:
>> trplot2(T1, 'frame', '1', 'color', 'b')
在高位版本
下,同样运行报错,报错提示如下:
>> trplot2(T1, 'frame', '1', 'color', 'b')
Unable to perform assignment because value of type 'se2' is not convertible to 'double'.出错 transl (第 88 行)t1(1:3,4,:) = x';出错 trplot2 (第 148 行)if all(size(T) == [3 3]) || norm(transl(T)) < eps原因:无法从 se2 转换为 double。
根据报错提示,T1
此时是se2
数据类型,而高版本
的trplot2
函数的第一个形参,要求数据类型为double
,那么,此处需要手动进行数据类型转换。可以参考该链接: (知乎)matlab中SE3是什么类型,怎么转换成double型矩阵?
经过实际尝试,使用tform
函数有效,转换如下:
>> T1_double = tform(T1)T1_double =0.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000
工作区中也可以观察到,数据类型变换成功。
这边需要再多说几句,知乎回答中提及的T1.T
方式尝试过,报错未识别类 'se2' 的方法、属性或字段 'T'。
,提及的另一种double(T1)
强制转换的方式也同样以失败告终。之后翻阅了tform
函数的文档看了一下,该函数应该是2022b版本以后引入的。
最终运行效果如下,记得补加上hold on
,原书中缺失,不然坐标轴刻度变化,不再是[0,5]:
>> T1_double = tform(T1)T1_double =0.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000
>> hold on
>> trplot2(T1_double, 'frame', '1', 'color', 'b')
3.4、完整绘制代码
>> tr = [1, 2]tr =1 2>> rot = rotz(30)rot =0.8660 -0.5000 00.5000 0.8660 00 0 1.0000>> T1 = se2(rot(1:2, 1:2), tr)T1 = se20.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000>> axis([0 5 0 5]);
>> T1_double = tform(T1)T1_double =0.8660 -0.5000 1.00000.5000 0.8660 2.00000 0 1.0000>> hold on
>> trplot2(T1_double, 'frame', '1', 'color', 'b')
>> rot2 = rotz(0)rot2 =1 0 00 1 00 0 1>> tr2 = [2, 1]tr2 =2 1>> T2 = se2(rot2(1:2, 1:2), tr2)T2 = se21 0 20 1 10 0 1>> T2_double = tform(T2)T2_double =1 0 20 1 10 0 1>> hold on
>> trplot2(T2_double, 'frame', '2', 'color', 'r');
>> T3 = T1 * T2T3 = se20.8660 -0.5000 2.23210.5000 0.8660 3.86600 0 1.0000>> T3_double = tform(T3)T3_double =0.8660 -0.5000 2.23210.5000 0.8660 3.86600 0 1.0000>> hold on;
>> trplot2(T3_double, 'frame', '3', 'color', 'g');
>> T4 = T2 * T1T4 = se20.8660 -0.5000 3.00000.5000 0.8660 3.00000 0 1.0000>> T4_double = tform(T4)T4_double =0.8660 -0.5000 3.00000.5000 0.8660 3.00000 0 1.0000>> hold on
>> trplot2(T4_double, 'frame', '4', 'color', 'c')
>> hold on;
>> P = [3; 2];
>> plot_point(P, '*');
最终效果如下:
3.5、获取点*
在坐标系1下的表示
原书中的inv
,在高版本使用时同样需要注意数据类型一致的问题:
% 原书中使用的变量名为P1
% 个人使用P_to_T1替换,感觉变量名意义更清晰明了些
>> P_to_T1 = inv(T1) * [P; 1]
错误使用 .*
times, .* requires both operands to be transformations or rotations (of the same type).出错 * (第 18 行)out = obj1 .* obj2;
报错原因为左侧inv(T1)
的结果仍为se2
类型,需要变为double
类型。验证如下:
>> Test = inv(T1)Test = se20.8660 0.5000 -1.8660-0.5000 0.8660 -1.23210 0 1.0000>> Test_double = tform(Test)Test_double =0.8660 0.5000 -1.8660-0.5000 0.8660 -1.23210 0 1.0000>> P_to_T1 = Test_double * [P; 1]P_to_T1 =1.7321-1.00001.0000
成功获取,点*
相对于坐标系{1}的表示为(1.7321,-1.0000)。
3.6、相对坐标获取完整代码
>> Test = inv(T1)Test = se20.8660 0.5000 -1.8660-0.5000 0.8660 -1.23210 0 1.0000>> Test_double = tform(Test)Test_double =0.8660 0.5000 -1.8660-0.5000 0.8660 -1.23210 0 1.0000>> P_to_T1 = Test_double * [P; 1]P_to_T1 =1.7321-1.00001.0000>> h2e(Test_double * e2h(P))ans =1.7321-1.0000>> homtrans(Test_double, P)ans =1.7321-1.0000>> P_to_T2 = homtrans(tform(inv(T2)), P)P_to_T2 =11
4、结语
平时工作为机械臂软件开发,书本中的matlab示例代码跑通的感觉还是挺舒服的。2.1节总体评价不错,通过二维演示了三维常见的齐次变换大致的使用思想。减去Z的维度,确实更方便初学者的理解。工作一年多,回过头来再看这些内容,也受益匪浅。
相关文章:

机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节)
机器人学、机器视觉与控制 上机笔记(第一版译文版 2.1章节) 1、前言2、本篇内容3、代码记录3.1、新建se23.2、生成坐标系3.3、将T1表示的变换绘制3.4、完整绘制代码3.5、获取点*在坐标系1下的表示3.6、相对坐标获取完整代码 4、结语 1、前言 工作需要&a…...
关于vue2+antd 信息发布后台不足的地方
有的写法可以cv 1.序号递增 {title: "序号",customRender: (text, record, index) > ${index 1},align: "center",}, 2.关于类型 {title: "类型",dataIndex: "type",align: "center",customRender: function (t) {sw…...
Ubuntu+Anaconda 常用指令记录
Anaconda 使用指令记录 1 创建环境 conda create -n name pythonx.x(python版本自己指定)例如 conda create --name myenv: 创建名为"myenv"的新环境。 conda activate myenv: 激活名为"myenv"的环境。 conda deactivate: 退出当前环境。 2 删除环境 c…...
P5732 【深基5.习7】杨辉三角 python解法
# 【深基5.习7】杨辉三角 ## 题目描述 给出 n<20,输出杨辉三角的前 n 行。 如果你不知道什么是杨辉三角,可以观察样例找找规律。 ## 输入格式 ## 输出格式 ## 样例 #1 ### 样例输入 #1 6 ### 样例输出 #1 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5…...

VitePress-12-markdown中使用vue的语法
前言 VitePress 中,markdown文档最终都会转换成为 html文件,我们在访问的时候,也是直接访问的 xxx.html 文件。而且,markdown文档会被作为 [vue单文件] 进行处理,因此,我们我们可以在文档中使用 vue 语法&…...

“bound drug/molecule”or “unbound drug/molecule”、molecule shape、sketching是什么?
“bound drug/molecule”or “unbound drug/molecule” For clarity, the following terms will be used throughout this study: “bound drug/molecule” (or “unbound drug/molecule”) refers to the drug/molecule that is bound (or unbound) to proteins [48]. 意思就是…...
深入理解C语言中的函数指针:概念、机制及实战应用
在C语言的世界里,函数是一等公民,可以被赋值给变量,这种特殊的变量就是我们今天要探讨的主角——函数指针。函数指针作为C语言中一种强大的工具,允许我们以间接方式调用函数,从而实现动态绑定、回调函数、策略模式等多…...

《UE5_C++多人TPS完整教程》学习笔记1 ——《P2 关于本课程(About This Course)》
本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P2 关于本课程(About This Course)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版,UP主(也是译者&…...

权限系统设计
权限系统设计 RBAC 基于角色的访问控制 ABAC 基于属性的访问控制 普通的系统无非 CRUD,那系统如何控制一个用户该看到哪些数据、能操作哪些功能?日常开发中最常用到 RBAC 和 OAuth2 这两种访问控制和授权方案 RBAC 基于角色的访问控制 所有的访问控制模…...

Ubuntu Desktop - Screenshot (截图工具)
Ubuntu Desktop - Screenshot [截图工具] 1. Search your computer -> Screenshot -> Lock to Launcher2. gnome-screenshot3. System Settings -> Keyboard -> ShortcutsReferences 1. Search your computer -> Screenshot -> Lock to Launcher 2. gnome-s…...

docker 1:介绍
docker 1:介绍 docker解决哪些问题: 传统APP在安装到不同电脑的时候可能会遇到依赖问题,比如缺少VS 20xx,软件无法运行”的情况。docker使用容器技术将软件 依赖打包为image包发布,解决了依赖问题。docker有一个官…...
RibbonBar RibbonPage切换事件
在开发的过程中,我们会用到点击切换page,来响应对应的事件,例如以下事件: 头文件中: void ribboncurrentPageIndexChanged(int index); 实现文件中: connect(ribbonBar(), SIGNAL(currentPageIndexChang…...

Conda历史版本下载地址和python对应关系
一、前言 因为Conda安装版本问题,带来了很多问题,虽然不能直接确定二者之间的关系,但是安装指定版本的conda,确实是一个比较好的方法。特此记忆。 二、下载地址 下载最新版本:Free Download | Anaconda 下载历史版本ÿ…...
Clickhouse查询语句执行过程
问题 简述clickhosue中一条select语句的执行过程,使用的引擎是ReplacingMergeTree。例如: select col1,col2 from table final prewhere col3 > ? and col4 ? and col5 ? -- col3为分区键,col4为二级索引,col5为主键字段 where col…...

【动态规划】【中位数】【C++算法】1478. 安排邮筒
# 作者推荐 【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目 本文涉及知识点 动态规划汇总 LeetCode1478. 安排邮筒 给你一个房屋数组houses 和一个整数 k ,其中 houses[i] 是第 i 栋房子在一条街上的位置,现需要在这条街上安排 k…...
C#系列-数据结构+递归算法+排序算法(3)
C#数据结构 在C#中,数据结构是用于组织和管理数据的方式,以便更有效地进行数据的存储、访问和操作。数据结构对于算法的性能和设计至关重要,因为它们决定了数据如何在内存中布局以及如何与算法进行交互。C#提供了许多内置的数据结构…...
Redis实现秒杀
前期准备 缓存选择考虑 Redis和Redis Cluster(分布式版本),是一个分布式缓存系统。其支持多种数据结构,也支持MQ。Redis在性能上做了大量优化。因此使用Redis或者Redis Cluster就可以轻松实现一个强大的秒杀系统。 用Redis的这…...
4 scala集合-Map
和 Java 一样,Scala 也有表示键值对(Key-Value)集合的 Map 数据结构。同样,Map 也分不可变和可变,不可变需要使用类 scala.collection.mutable.Map。 1 不可变 Map 可以使用以下语法定义不可变 Map 对象 val/var ma…...
QT 对象树模型
QObject是Qt里边绝大部分类的根类 QObject对象之间是以对象树的形式组织起来的。 当两个QObject(或子类)的对象建立了父子关系的时候。子对象就会加入到父对象的一个成员变量叫children(孩子)的list(列表)…...

ubuntu快速安装miniconda
ubuntu快速安装miniconda 环境 ubuntu.22.04 显卡 RTX 3050 关于选择Miniconda还是Anaconda的问题,Anaconda安装包比较大,耗时比较长,如果你是绝对的初学者,选择Anaconda会比较稳妥一些;否则建议你还是选择Miniconda安…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...