实例8:机器人的空间描述和变换仿真

news2024/10/1 9:39:09

实例8:机器人的空间描述和变换仿真

实验目的

  1. 通过刚体与刚体的平动、转动基础知识的学习,熟悉位姿的描述
  2. 通过Python编程实践,可视化学习坐标系的变换,熟悉空间变换

实验要求

建立一个原点位于零点的三维正交坐标系,x、y、z轴分别用红、绿、蓝三色表示。

实验知识

1.实例介绍

在这个实例中,我们将学习机器人运动学的基础-空间的描述与变换。
空间的描述与变换将定性定量地解释四足机器狗上零件的基本运动,四足机器狗mini pupper上有12个舵机,每个舵机都有自己的空间位置和运动,为了表达舵机等零件的本身的位置和姿态,我们需要定义坐标系并给出表示的规则,这些位置和姿态的描述将作为表达线速度、角速度、力和力矩的基础。

为了描述空间中物体的位置和姿态,一般可以在物体上设置一个坐标系,称为物体坐标系,在参考坐标系中描述通过位置和姿态来描述这个物体坐标系。任一的坐标系也可以作为另一个坐标系的参考坐标系,这就涉及到了坐标系和坐标系之间的位置和姿态的变换,称之为位姿变换。因此,要了解mini pupper的运动,需要研究同一物体在不同坐标系中的位置和姿态的描述方法,以及量化计算位置和姿态的数学方法。

图片1: 相对于坐标系的矢量p21

2.什么是刚体?

为了简化机器人模型,我们将四足机器狗mini pupper上的各关节零件视作刚体(rigid body),刚体是在运动中和受到力的作用后,形状和大小不变,而且内部各点的相对位置不变的物体。

2.怎样描述刚体的位姿?

位置描述

为了描述mini pupper上的零件在空间中的位置,在数学中,我们通常用三个正交的带有箭头的单位矢量来描述一个三维坐标系,在这里称为世界坐标系,世界坐标系 A A A中的点 A P ^{A}P AP可以用一个 3 × 1 3\times1 3×1的位置矢量来表达,这个矢量可被认为是空间中的一个位置。
A P = [ p x p y p z ] ^AP= \left[ \begin{matrix} p_x\\ p_y\\ p_z \end{matrix} \right] AP= pxpypz
A P ^AP AP:P点相对于坐标系 A A A的位置矢量
p x p_x px: P向量相对于坐标系 A A A x x x轴方向的分量

姿态描述

mini pupper上的零件刚体除了需要表示位置,通常还需要描述它的姿态,为了描述这个姿态,我们将在物体上固定一个坐标系并且给出这个坐标系相对参考坐标系的描述。
也就是说,我们用一个固定在物体上的坐标系来描述这个物体的姿态,而这个坐标系的描述可以利用相对参考系的三个主轴单位矢量来描述。
X B ^ \hat{X_B} XB^ Y B ^ \hat{Y_B} YB^ Z B ^ \hat{Z_B} ZB^ 来表示坐标系 B B B主轴方向的单位矢量,如果用坐标系 A A A来作为参考系,则写作 A X B ^ \hat{^AX_B} AXB^ A Y B ^ \hat{^AY_B} AYB^ A Z B ^ \hat{^AZ_B} AZB^ ,按前述顺序组成 3 × 1 3 \times1 3×1的矩阵,这个矩阵被称为旋转矩阵
旋转矩阵 B A R ^A_BR BAR是坐标系 B B B相对于参考坐标系 A A A的表达:

B A R = ( A X B ^ A Y B ^ A Z B ^ ) = [ X ^ B ⋅ X ^ A Y ^ B ⋅ X ^ A Z ^ B ⋅ X ^ A X ^ B ⋅ Y ^ A Y ^ B ⋅ Y ^ A Z ^ B ⋅ Y ^ A X ^ B ⋅ Z ^ A Y ^ B ⋅ Z ^ A Z ^ B ⋅ Z ^ A ] (旋转矩阵) ^A_BR =(\hat{^AX_B}\quad\hat{^AY_B}\quad\hat{^AZ_B} ) = \left[ \begin{matrix} \hat X_B\cdot \hat X_A& \hat Y_B\cdot \hat X_A & \hat Z_B\cdot \hat X_A \\ \hat X_B\cdot \hat Y_A& \hat Y_B\cdot \hat Y_A&\hat Z_B\cdot \hat Y_A \\ \hat X_B\cdot \hat Z_A & \hat Y_B\cdot \hat Z_A & \hat Z_B\cdot \hat Z_A \end{matrix} \right] \tag{旋转矩阵} BAR=(AXB^AYB^AZB^)= X^BX^AX^BY^AX^BZ^AY^BX^AY^BY^AY^BZ^AZ^BX^AZ^BY^AZ^BZ^A (旋转矩阵)
B A R ^A_BR BAR:坐标系 B B B相对于参考坐标系 A A A的旋转矩阵
X ^ B \hat X_B X^B:坐标系 B B B x x x方向的单位矢量
X ^ A \hat X_A X^A:坐标系 A A A x x x方向的单位矢量

位姿描述

在四足机器狗mini pupper的运动学中,位置和姿态经常成对出现,称之为位姿
结合位置描述与姿态描述,得出一个位姿 { B } \left\{ B \right\} {B}可以等价地用一个位置矢量 A P B O R G ^AP_{B ORG} APBORG和一个旋转矩阵 B A R ^A_BR BAR来描述:
{ B } = { B A R , A P B O R G } \left\{ B \right\}=\left\{ ^A_BR ,^AP_{B ORG}\right\} {B}={BAR,APBORG}
A P B O R G ^AP_{B ORG} APBORG:确定位姿 { B } \left\{ B \right\} {B}的原点的位置矢量,ORG为Origin,即原点之意

4.如何描述刚体的平移与旋转?

平移

在了解完位置、姿态、位姿的概念后,我们将学习如何从一个坐标系变换到另一个坐标系,这使得mini pupper的刚体零件可以在不同的参考坐标系中被表达为一个相同的量。
图片2:位姿变换图

下面,就让我们来尝试将一个坐标平移来体会四足机器狗mini pupper上的刚体零件的运动。
坐标平移是简单的运动,在 { A } \left\{ A \right\} {A} { B } \left\{ B \right\} {B}的姿态相同时, { B } \left\{ B \right\} {B}不同与 { A } \left\{ A \right\} {A}的只有平移,所以可以用一个位置矢量 A P B O R G ^AP_{B ORG} APBORG来描述 { B } \left\{ B \right\} {B}相对于 { A } \left\{ A \right\} {A}的位置。

图片3:坐标平移图
以下为矢量相加的办法求点 P P P相对于 { A } \left\{ A \right\} {A}的表示 A P ^AP AP
A P = B P + A P B O R G ^AP= {\kern 2pt}^BP+ {\kern 2pt}^AP_{BORG} AP=BP+APBORG

旋转

通常认为, { B } \left\{ B \right\} {B}相对于 { A } \left\{ A \right\} {A}的旋转矩阵表示为 B A R ^A_BR BAR
旋转矩阵各列的模为1,各单位矢量均相互正交,可得:
B A R = B A R − 1 = A B R T ^A_BR = ^A_BR^{-1}=^B_AR^T BAR=BAR1=ABRT

对于 A P = B P + A P B O R G ^AP= {\kern 2pt}^BP+ {\kern 2pt}^AP_{BORG} AP=BP+APBORG
可以用更简洁的形式:一个 4 × 4 4 \times 4 4×4矩阵形式的算子,并用一个 4 × 1 4\times 1 4×1的位置矢量。

( A P 1 ) = [ A B R A P B O R G 0 0 0 1 ] ( B P 1 ) \left( \begin{matrix} ^AP \\ 1 \end{matrix} \right)= \left[ \begin{matrix} A_BR &^AP_{BORG}\\ 0{\kern 3pt}0{\kern 3pt}0&1 \end{matrix} \right] \left( \begin{matrix} ^BP \\ 1 \end{matrix} \right) (AP1)=[ABR000APBORG1](BP1)

这个 4 × 4 4\times 4 4×4矩阵被称为齐次变换矩阵,它以普通矩阵的形式表示了一般变换中的旋转以及平移。
简写为:
A P = B A T B P ^AP= {\kern 2pt}^A_BT {\kern 2pt}^BP AP=BATBP

5. matplotlib

matplotlib是Python语言及其数值计算库NumPy的绘图库。它的设计与MATLAB非常类似,能够在Python中方便地绘制图像。
参考链接:matplotlib官方文档

6. numpy

NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库,因此可以用来计算坐标系的变换。
参考链接:numpy官方文档

7. 绘制向量的函数

ax.quiver(起点x, 起点y, 起点z,x方向数值, y方向数值, z方向数值,arrow_length_ratio=箭头箭身比, color="颜色") 

8. 用户的输入部分

move_pre= input("请输入坐标系原点相对参考坐标系原点平移的x、y、z分量:")
move = [int(n) for n in move_pre.split()]
print(move)
rotate_pre= input("请输入坐标系绕参考坐标系x轴、y轴、z轴依次旋转的角度:") # 旋转采用Fixed Angles模式
rotate = [int(n) for n in rotate_pre.split()]
print(rotate)

9. 安装matplotlib环境

sudo apt install pip # 安装pip
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 换源
sudo pip install matplotlib # 安装matplotlib

请添加图片描述

实验步骤

1. 编写Python程序 frame_transformation.py

import matplotlib.pyplot as plt  # 引入matplotlib库
import numpy as np  # 引入numpy库

def rotate_X(x, y, z, alpha):
    alpha = alpha * (np.pi / 180)
    x_r = x
    y_r = np.cos(alpha)*y - np.sin(alpha)*z
    z_r = np.sin(alpha)*y + np.cos(alpha)*z
    print(f"Test_X-axis:{(x, y, z)} rotate {alpha*(180/np.pi)} degrees,result: {(x_r, y_r, z_r)}")
    return x_r, y_r, z_r

def rotate_Y(x, y, z, beta):
    beta = beta * (np.pi / 180)
    x_r = np.cos(beta)*x + np.sin(beta)*z
    y_r = y
    z_r = -np.sin(beta)*x + np.cos(beta)*z
    print(f"Test_Y-axis:{(x, y, z)} rotate {alpha*(180/np.pi)} degrees,result: {(x_r, y_r, z_r)}")
    return x_r, y_r, z_r

def rotate_Z(x, y, z,  gamma):
    gamma = gamma * (np.pi / 180)
    x_r = np.cos(gamma)*x - np.sin(gamma)*y
    y_r = np.sin(gamma)*x + np.cos(gamma)*y
    z_r = z
    print(f"Test_Z-axis:{(x, y, z)} rotate {alpha*(180/np.pi)} degrees,result: {(x_r, y_r, z_r)}")
    return x_r, y_r, z_r

def draw_before(px,py,pz):
    x_vector = ax.quiver(origin[0], origin[1], origin[2],
                         ac2 * x_axis_unit_vector[0], ac2 * x_axis_unit_vector[1], ac2 * x_axis_unit_vector[2],
                         arrow_length_ratio=0.1, color="black")  # 绘制A坐标系的x单位向量
    y_vector = ax.quiver(origin[0], origin[1], origin[2],
                         ac2 * y_axis_unit_vector[0], ac2 * y_axis_unit_vector[1], ac2 * y_axis_unit_vector[2],
                         arrow_length_ratio=0.1, color="black")  # 绘制A坐标系的y单位向量
    z_vector = ax.quiver(origin[0], origin[1], origin[2],
                         ac2 * z_axis_unit_vector[0], ac2 * z_axis_unit_vector[1], ac2 * z_axis_unit_vector[2],
                         arrow_length_ratio=0.1, color="black")  # 绘制A坐标系的z单位向量
    p_vector = ax.quiver(origin[0], origin[1], origin[2],
                         px, py, pz,
                         arrow_length_ratio=0.1, color="red")  # 绘制A坐标系的p向量
    print(px,py,pz)

# plot_init
fig = plt.figure() # 建立图像
ax = fig.add_subplot(projection="3d")  # 为图像添加三维坐标系
#ax.grid(False)  # 取消网格线,如需要网格线,请注释该行
# Setting the axes properties
ax.set(xlim3d=(0, 5), xlabel='X')
ax.set(ylim3d=(0, 5), ylabel='Y')
ax.set(zlim3d=(0, 5), zlabel='Z')

# variable_init
origin = [0, 0, 0]
x_axis_unit_vector = [1, 0, 0]
y_axis_unit_vector = [0, 1, 0]
z_axis_unit_vector = [0, 0, 1]
#ac = 6  # 坐标轴底色向量增益系数
ac2 = 4  # A坐标系增益系数

#绘制坐标轴底色向量
# ax.quiver(origin[0], origin[1], origin[2],
#           ac*x_axis_unit_vector[0], ac*x_axis_unit_vector[1], ac*x_axis_unit_vector[2],
#           arrow_length_ratio=0.1, color="black")  # 绘制x方向底色向量
# ax.quiver(origin[0], origin[1], origin[2],
#           ac*y_axis_unit_vector[0], ac*y_axis_unit_vector[1], ac*y_axis_unit_vector[2],
#           arrow_length_ratio=0.1, color="black")  # 绘制y方向底色向量
# ax.quiver(origin[0], origin[1], origin[2],
#           ac*z_axis_unit_vector[0], ac*z_axis_unit_vector[1], ac*z_axis_unit_vector[2],
#           arrow_length_ratio=0.1, color="black")  # 绘制z方向底色向量

# main
#move_pre= input("请输入坐标系原点相对参考坐标系原点平移的x、y、z分量:")
#move = [int(n) for n in move_pre.split()]
#print(move)


vector_in_A_pre= input("请输入该向量在参考坐标系A中的xyz分量:")
vector_in_A = [int(n) for n in vector_in_A_pre.split()]
print(vector_in_A)
rotate_pre= input("请输入向量绕参考坐标系x轴、y轴、z轴依次旋转的角度(角度制):") # 旋转采用Fixed Angles模式
rotate = [int(n) for n in rotate_pre.split()]
print(rotate)
alpha = rotate[0]
beta = rotate[1]
gamma = rotate[2]
draw_before(vector_in_A[0], vector_in_A[1], vector_in_A[2]) # 绘制原坐标系及原指定向量
first_vector = rotate_X(vector_in_A[0], vector_in_A[1], vector_in_A[2],alpha)
p1_vector = ax.quiver(origin[0], origin[1], origin[2],
                     first_vector[0], first_vector[1], first_vector[2],
                     arrow_length_ratio=0.1, color="orange")  # 绘制绕x旋转后的p向量
second_vector = rotate_Y(first_vector[0], first_vector[1], first_vector[2],beta)
p2_vector = ax.quiver(origin[0], origin[1], origin[2],
                     second_vector[0], second_vector[1], second_vector[2],
                     arrow_length_ratio=0.1, color="green")  # 绘制绕y旋转后的p向量
third_vector = rotate_Y(second_vector[0], second_vector[1], second_vector[2],gamma)
p3_vector = ax.quiver(origin[0], origin[1], origin[2],
                     third_vector[0], third_vector[1], third_vector[2],
                     arrow_length_ratio=0.1, color="blue")  # 绘制绕z旋转后的p向量

plt.show()  # 绘制

2. 运行程序,观察效果

在frame_transformation.py的目录下执行以下命令:

sudo python frame_transformation.py

输入对应的转动角度,此时应观察到向量绕各轴依次转动后的变化。
在这里插入图片描述
可视化动画:https://www.andre-gaschler.com/rotationconverter/
https://juejin.cn/post/7094065076008648718

实验总结

经过本知识点的学习和实验操作,你应该能达到以下水平:

知识点内容了解熟悉掌握
刚体刚体的平动、转动基础知识
位姿位姿的描述
坐标变换坐标系之间的变换

版权信息:教材尚未完善,此处预留版权信息处理方式
mini pupper相关内容可访问:https://github.com/mangdangroboticsclub

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

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

相关文章

SQL零基础入门学习(十二)

SQL零基础入门学习(SQL约束) SQL CREATE INDEX 语句 CREATE INDEX 语句用于在表中创建索引。 在不读取整个表的情况下,索引使数据库应用程序可以更快地查找数据。 索引 您可以在表中创建索引,以便更加快速高效地查询数据。 用…

WooCommerce 上传文件 Vanquish v71.6

今天用wp 搭一个b2c外贸跨境电商网站 找 了一个文件上传插件,可以 上传无限数量的文件,没有文件大小限制WooCommerce 上传文件允许您上传无限数量的文件,没有任何文件大小限制。得益于其创新的块上传技术,它可以不受限制地上传任何…

【华为OD机试模拟题】用 C++ 实现 - 数据分类(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

记一次SSM项目启动过程中遇到的问题(找不到符号)

最近拿了朋友的SSM项目过来参考一下开发过程,然后我这边个人情况是没有学过Java的,环境也不太清楚,虽然之前有在学校过程中做过一个旅游网站类似的SSM项目,电脑环境配置还是有些不太了解,bug修了2天大概,然…

windows下编译leveldb(动态库+静态库)

环境准备 1)下载cmake并安装 下载路径: https://cmake.org/download/2)下载leveldb源码 git clone https://github.com/google/leveldb.git3)下载googletest和benchmark,cmake编译时需要 # 进入leveldb源码路径下的third_part…

干了2年的手工点点点,感觉每天浑浑噩噩,我的自动化测试之路...

作为一个测试人员,从业年期从事手工测试的工作是没有太多坏处的,当然,如果一直点来点去那么确实自身得不到提高,这时候选择学习自动化测试是一件很有必要的事情,一来将自己从繁重的重复工作中解放出来,从事…

操作系统——6.系统调用

目录 1.概述 2.系统调用的定义和作用 2.1 定义 2.2 功能 2.3 分类 3.系统调用和库函数的区别 4.系统调用背后的过程 5.小结 1.概述 这篇文章我们主要来介绍一下操作系统中的系统调用,下面来看一下具体的框架图: 2.系统调用的定义和作用 2.1 定…

Mysql索引学习

1. 索引 1.1 索引概述 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引…

Linux->进程优先级

目录 1. 优先级的概念 2. 优先级的运作方式 3. Linux下查看进程优先级以及调整 3.1 查看进程优先级 3.2 修改进程优先级 1. 优先级的概念 1. cpu资源分配的先后顺序,就是指进程的优先权(priority)。 2. 优先权高的进程有优先执行权利。配…

数据结构:二叉树概念篇(算法基础)

目录 一.有向树的图论基础 1.有向树的相关基本概念 有向树的基本定义: 有向树的结点的度: 有向树的度: 有向树的根结点,分枝结点,叶结点: 树的子树: 树结点的层次: 树的高度: 2.一个基本的数学结论 3.有序有向树 二.数据结构中树的顺序存储结构与链式存…

【华为OD机试模拟题】用 C++ 实现 - 星际篮球争霸赛(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【log】操作类日志处理 与 报错类日志处理logback

文章目录一、操作类日志处理【环绕增强】aop环绕增强导包第一步:自定义注解interface第二步:在Controller写一个测试的方法:第三步:编写LogAspect增强类与增强方法日志写入数据库(使用mybatis)第一步&#…

C/C++每日一练(20230225)

目录 1. 工龄问题求解 ★ 2. 字符图形输出 ★★ 3. LRU 缓存机制 ★★★ 1. 工龄问题求解 给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。输入首先给出正整数N,即员工总人数; 随后给出N个整数,即每个员工…

图像分割评价指标:Dice和MIoU

目录Dice理论代码MIou理论查准率 precison查全率 recallMIoU 平均交并比代码高效的矩阵运算低效的好理解的计算混淆矩阵Dice和MIoU两者的关系参考链接Dice 理论 Dice用来衡量预测结果pred和标签label的相似度,公式如下图所示,即两个集合的交集/并集。 …

Java-多线程-增强篇-锁强化第3篇

Java集合框架中的锁 今天我们继续来学习锁 字符串操作中的锁 String是线程安全的,因为使用final修饰Stringbuilder 是线程不安全的,其方法没有使用synchronized修饰StringBuffer 是线程安全的,其方法使用synchronized修饰 List集合中的锁 …

【人工智能 AI】可以从 RPA 中受益的 10 个行业 10 Industries That Can Benefit From RPA

目录 RPA技术介绍 Which industries can use robotic process automation?哪些行业可以使用机器人过程自动化? Robotic process automation in the retail industry零售业中的机器人过程自动化 Robotic process automation in the construction industry建筑行业的机器人…

RebbitMQ 消息队列(高级应用)

RabbitMQ 高级特性 消息可靠性投递,consumer ACK,消费端限流,TTL,死信队列,延迟队列,日志与监控,消息可靠性与追踪,管理 RabbitMQ 应用问题 消息可靠性保障,消息幂等性…

JavaScript 基础【快速掌握知识点】

目录 为什么要学JavaScript? 什么是JavaScript 特点: 组成: JavaScript的基本结构 基本结构 内部引用 外部引用 console对象进行输出 JavaScript核心语法 1、变量声明 2、数据类型 3、运算符 4、条件语句 5、循环语句 6、数组 7…

【shell】for while 循环的例子,快速了解

for 循环读一个文件的每一行 for i in cat temp.list;do echo $i;done for ip in $(cat ip.list);do ping -c 2 $ip;done循环打印数字 for a in {1…5};do echo $a;done for a in {1…5…2};do echo $a;done #等差 for a in $(seq 1 5);do echo $a;done for a in $(seq 1 2 5)…

内网穿透常用方法系列总结

前言在内网渗透时,一个WebShell或CobaltStrike、Metasploit上线等,只是开端,更多是要内网横向移动,扩大战果,打到核心区域。但后渗透的前提是需要搭建一条通向内网的“专属通道”,才能进一步攻击。可实战中…