机器人学、机器视觉与控制 上机笔记(第一版译文版 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安…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
