机器人学、机器视觉与控制 上机笔记(第一版译文版 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安…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...