apriltag使用之三:机械臂与Apriltag码对齐

2023-12-02 01:08

本文主要是介绍apriltag使用之三:机械臂与Apriltag码对齐,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相机到Apriltag的对齐

上面是一个简单的手画的关于机器人、摄像头以及Apriltag码之间的位置关系图。机器人的基坐标系{s}由 ( x s , y s , z s , t s ) (\mathbf{x_s,y_s,z_s,t_s}) (xs,ys,zs,ts)表示,摄像头的初始位置的坐标系{c}由 ( x c , y c , z c , t c ) (\mathbf{x_c,y_c,z_c,t_c}) (xc,yc,zc,tc)表示,apriltag码的坐标系{a}由 ( x a , y a , z a , t a ) \mathbf{(x_a,y_a,z_a,t_a)} (xa,ya,za,ta)表示。其中 t \mathbf{t} t是各坐标系原点相对于全局参考坐标系中的位置, x , y , z \mathbf{x,y,z} x,y,z则是各坐标系的坐标轴单位向量在全局参考坐标系的表示,这也形成各坐标系相对于全局参考坐标系的旋转矩阵 R = [ x , y , z ] \mathbf{R=[x,y,z]} R=[x,y,z]。同时我们使用坐上标表示父坐标系,右下标表示子坐标系,例如相机坐标系的旋转矩阵为 s R c = [ s x c , s y c , s z c ] ^s\mathbf{R}_c=[^s\mathbf{x}_c,^s\mathbf{y}_c,^s\mathbf{z}_c] sRc=[sxc,syc,szc]

通常我们可以将全局参考坐标系就设在机器人的基坐标系,因此有
t s = ( 0 , 0 , 0 ) T x s = ( 1 , 0 , 0 ) T y s = ( 0 , 1 , 0 ) T z s = ( 0 , 0 , 1 ) T \begin{aligned} \mathbf{t}_s=(0,0,0)^T \\ \mathbf{x}_s=(1,0,0)^T \\ \mathbf{y}_s=(0,1,0)^T \\ \mathbf{z}_s=(0,0,1)^T \\ \end{aligned} ts=(0,0,0)Txs=(1,0,0)Tys=(0,1,0)Tzs=(0,0,1)T

通过Apriltag检测,我们知道了Apriltag在摄像头坐标系{c}下的方位为 [ c R a ∣ c t a ] [^c\mathbf{R}_a|^c\mathbf{t}_a] [cRacta],目标是:获得相机坐标系相对与全局参考坐标系的方位 [ s R c ′ ∣ s t c ′ ] [^s\mathbf{R}_{c'}|^s\mathbf{t}_{c'}] [sRcstc],使得相机在保持相同距离的情况下视角正对于Apriltag码。

从上图中我们可知,新的相机是与Apriltag码的方向相同的,既有 s R c ′ = s R a ^s\mathbf{R}_{c'}=^s\mathbf{R}_a sRc=sRa。而我们肯定是知道运动中的机器人末端的相机在全局坐标系下的方位的,即 [ s R c ∣ s t c ] [^s\mathbf{R}_c|^s\mathbf{t}_c] [sRcstc]。从相机坐标到全局参考坐标的变换为:
s T c = [ s R c s t c 0 1 ] ^s\mathbf{T}_c=\left[\begin{array}{ccc} ^s\mathbf{R}_c & ^s\mathbf{t}_c \\ 0 & 1 \end{array}\right] sTc=[sRc0stc1]
Apriltag码在全局坐标系中的位置为 s T c c t a ^s\mathbf{T}_c ^c\mathbf{t}_a sTccta。所以Apriltag码在全局参考坐标系下的方位就为 [ s R a ∣ s t a ] = [ s R c ⋅ c R a ∣ s T c ⋅ c t a ] [^s\mathbf{R}_a|^s\mathbf{t}_a]=[^s\mathbf{R}_c\cdot ^c\mathbf{R}_a|^s\mathbf{T}_c\cdot^c\mathbf{t}_a] [sRasta]=[sRccRasTccta]。另外可以得出Apriltag码坐标系到全局坐标系的 s T a ^s\mathbf{T}_a sTa为:
s T a = [ s R a s t a 0 1 ] = [ s R c ⋅ c R a s T c ⋅ c t a 0 1 ] ^s\mathbf{T}_a=\left[\begin{array}{ccc} ^s\mathbf{R}_a & ^s\mathbf{t}_a \\ 0 & 1 \end{array}\right] = \left[\begin{array}{ccc} ^s\mathbf{R}_c\cdot ^c\mathbf{R}_a & ^s\mathbf{T}_c\cdot^c\mathbf{t}_a \\ 0 & 1 \end{array}\right] sTa=[sRa0sta1]=[sRccRa0sTccta1]

然后需要确定的就是新的相机位置 s t c ^s\mathbf{t}_c stc,该位置其实在Apriltag码的坐标系下是 a t c = ( 0 , 0 , − ∣ ∣ c t a ∣ ∣ ) ^a\mathbf{t}_c=(0,0,-||^c\mathbf{t}_a||) atc=(0,0,cta),将其通过 s T a ^s\mathbf{T}_a sTa变换到全局坐标系下即可,即$^s\mathbf{t}_c = s\mathbf{T}_a\cdota\mathbf{t}_c $。

关于摄像头在机械臂上的位置

一般情况下,摄像头都是安装在机械臂的末端执行器的一侧的,所以就存在一个 t T c ^t\mathbf{T}_c tTc表示相机到机械臂末端的位置变换,并且有 s T c = s T t ⋅ t T c ^s\mathbf{T}_c=^s\mathbf{T}_t\cdot^t\mathbf{T}_c sTc=sTttTc。因此当新的 s T c ^s\mathbf{T}_c sTc计算出来后,还要计算 s T t = s T c ⋅ t T c − 1 ^s\mathbf{T}_t=^s\mathbf{T}_c\cdot ^t\mathbf{T}^{-1}_c sTt=sTctTc1来得到机械臂末端的方位,以便使用Moveit来控制机械臂运动。

代码

首先,我们假设以及执行了另外一个ROS节点在不断地检测摄像头图像中的Apriltag码,并将检测结果存放到名为"/apriltag/pose"的Topic中。

下面给出主要的执行代码。注意其中aligning函数执行了两次。因为第一次摄像头距离Apriltag码比较远,对方位的估计会比较粗糙,所以当第一次使得摄像头比较近时,再一次执行该操作可以使对齐更加精确。

import cv2
import numpy as np
import rospy
import moveit_commander
from geometry_msgs.msg import *
import tf_conversionsclass FindApriltag(object):def __init__(self):super(FindApriltag, self).__init__()group_name = "arm"  # 这是对机器人进行moveit配置定义的关节组名称self.group = moveit_commander.MoveGroupCommander(group_name)print("effector_link=", self.group.get_end_effector_link())self.pose_pub = rospy.Subscriber("/apriltag/pose", PoseArray, self.poseCB)self.poseArr =PoseArray()# 等待Topic订阅rospy.sleep(1)def poseCB(self, poseArr):self.poseArr = poseArrdef aligning(self):pose_st = self.group.get_current_pose()# 获得Apriltag相对于摄像头的方位for i in (0,1,2,3):if len(self.poseArr.poses)<1:print "There is no Apriltag"else:print "Apriltag found"breakrospy.sleep(0.1)pose_ca= self.poseArr.poses[0]# 计算机械臂末端到全局坐标系中的方位new_pose_st = self.compute_new_pose_st(pose_st.pose, pose_ca)# 运动到新位置pose_st.pose = new_pose_stself.move_to_pose(pose_st)def run(self):#1. 运动到指定位置,以便查找Apriltagpose_st = self.group.get_current_pose()print("cur pose_st: ", pose_st.pose)pose_st.pose.orientation.x = 1; pose_st.pose.orientation.y=0pose_st.pose.orientation.z = 0; pose_st.pose.orientation.w=0pose_st.pose.position.x = 0;  pose_st.pose.position.z =0.5pose_st.pose.position.y = 0.5self.move_to_pose(pose_st)self.aligning()self.aligning() # 再一次def main():rospy.init_node('find_apriltag', anonymous=True)app = FindApriltag()app.run()rospy.spin()returnif __name__ == '__main__':main()

实验

下面的动画显示了一个对齐的过程。其中将相机到Apriltag码的距离设置为0.15米。

这篇关于apriltag使用之三:机械臂与Apriltag码对齐的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/443382

相关文章

Swagger2与Springdoc集成与使用详解

《Swagger2与Springdoc集成与使用详解》:本文主要介绍Swagger2与Springdoc集成与使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1. 依赖配置2. 基础配置2.1 启用 Springdoc2.2 自定义 OpenAPI 信息3.

Golang interface{}的具体使用

《Golanginterface{}的具体使用》interface{}是Go中可以表示任意类型的空接口,本文主要介绍了Golanginterface{}的具体使用,具有一定的参考价值,感兴趣的可以了... 目录一、什么是 interface{}?定义形China编程式:二、interface{} 有什么特别的?✅

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

windows和Linux安装Jmeter与简单使用方式

《windows和Linux安装Jmeter与简单使用方式》:本文主要介绍windows和Linux安装Jmeter与简单使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows和linux安装Jmeter与简单使用一、下载安装包二、JDK安装1.windows设

Spring 缓存在项目中的使用详解

《Spring缓存在项目中的使用详解》Spring缓存机制,Cache接口为缓存的组件规范定义,包扩缓存的各种操作(添加缓存、删除缓存、修改缓存等),本文给大家介绍Spring缓存在项目中的使用... 目录1.Spring 缓存机制介绍2.Spring 缓存用到的概念Ⅰ.两个接口Ⅱ.三个注解(方法层次)Ⅲ.

PyTorch中cdist和sum函数使用示例详解

《PyTorch中cdist和sum函数使用示例详解》torch.cdist是PyTorch中用于计算**两个张量之间的成对距离(pairwisedistance)**的函数,常用于点云处理、图神经网... 目录基本语法输出示例1. 简单的 2D 欧几里得距离2. 批量形式(3D Tensor)3. 使用不

C#使用MQTTnet实现服务端与客户端的通讯的示例

《C#使用MQTTnet实现服务端与客户端的通讯的示例》本文主要介绍了C#使用MQTTnet实现服务端与客户端的通讯的示例,包括协议特性、连接管理、QoS机制和安全策略,具有一定的参考价值,感兴趣的可... 目录一、MQTT 协议简介二、MQTT 协议核心特性三、MQTTNET 库的核心功能四、服务端(BR

使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案

《使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案》在SpringBoot应用中,我们经常使用​​@Cacheable​​注解来缓存数据,以提高应用的性能... 目录@Cacheable注解Redis时,Redis宕机或其他原因连不上,继续调用原方法的解决方案1

java中XML的使用全过程

《java中XML的使用全过程》:本文主要介绍java中XML的使用全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录什么是XML特点XML作用XML的编写语法基本语法特殊字符编写约束XML的书写格式DTD文档schema文档解析XML的方法​​DOM解析XM

使用Java实现Navicat密码的加密与解密的代码解析

《使用Java实现Navicat密码的加密与解密的代码解析》:本文主要介绍使用Java实现Navicat密码的加密与解密,通过本文,我们了解了如何利用Java语言实现对Navicat保存的数据库密... 目录一、背景介绍二、环境准备三、代码解析四、核心代码展示五、总结在日常开发过程中,我们有时需要处理各种软