基于FANUC工业机器人的坐标系转换、多视角拼接与三维重建

0.简介

  • 总体任务:机械臂末端安装三维相机,绕着工件进行拍摄,并在计算机中将每次拍摄的点云合并在同一个坐标系下,从而获得更加完整全面的点云。
  • 机械臂:FANAUC
  • 相机:梅卡曼德
  • 技术方案:使用相机外参、机械臂位姿进行坐标系转换,将不同视角点云坐标系都转换到机器人基座(基于ICP或深度学习的点云匹配也可以实现类似效果,但实际应用鲁棒性不够,对视角间点云的重叠度要求较高或是难以获取相似度高的大量训练数据)

1.多位姿点云拍摄与读取

  • 机械臂移动拍摄工件不同视角,记录下每个视角的点云、机械臂位姿
  • 相关数据
  • 在这里插入图片描述
  • 点云读取及简单处理可以参考这里
  • 注意:梅卡曼德拍摄后点云的xyz坐标单位是m,而FANUC等转换矩阵的单位是mm,所以要注意单位统一
pcd = o3d.io.read_point_cloud('datasFANUC/' + 'point_cloud_00000' + '.ply')
pcd_np = np.array(pcd.points) * 1000
pcd.points = o3d.utility.Vector3dVector(pcd_np)
pcd.paint_uniform_color([0, 1.0, 0])
o3d.visualization.draw_geometries([pcd])

在这里插入图片描述

2.手眼标定的外参转换矩阵

  • 通过梅卡曼德官方软件与FANUC配合完成相机内外参的标定,外参标定结果如下(使用和FANUC相同的表示方式):
x,y,z,w,p,r = 70.5, 269.927, -33.947, -0.85, 0.78, 147.95

3.FANUC机械臂转换矩阵

  • FANUC工业机器人采用的是定角旋转方式,法兰(机械臂末端坐标系)到机械臂基座坐的相对位置由X- Y-Z,W-P-R表示,W表示绕X轴旋转的角度;P表示绕Y轴旋转的角度;R表示绕Z轴旋转的角度;它们的旋转方向由右手定则判断。(参考资料)
  • 定角旋转:定角旋转与欧拉角旋转类似,只不过定角旋转的转轴一直是最原始的坐标系转轴(该轴不随着旋转而变化)
  • 三次绕固定轴旋转(定角旋转)的最终姿态和以相反顺序三次绕运动坐标轴旋转(欧拉角旋转)的最终姿态相同(机器人学——姿态描述方法(欧拉角,固定角,D-H法,绕定轴旋转))
  • 机器人默认显示旋转顺序是WPR,即依次绕XYZ轴进行旋转,对应的旋转矩阵为RZRYRX
  • 绕定轴旋转的相关程序如下:
'''
旋转矩阵相关
'''
def Rx(theta):
    '''
    绕X轴旋转矩阵
    '''
    RX = np.array([[1, 0, 0],
                   [0, math.cos(theta), -1*math.sin(theta)],
                   [0, math.sin(theta), math.cos(theta)]])
    return RX
def Ry(theta):
    '''
    绕Y轴旋转矩阵
    '''
    RY = np.array([[math.cos(theta), 0, math.sin(theta)],
                   [0, 1, 0],
                   [-1*math.sin(theta), 0, math.cos(theta)]])
    return RY
def Rz(theta):
    '''
    绕Z轴旋转矩阵
    '''
    RZ = np.array([[math.cos(theta), -1*math.sin(theta), 0],
                   [math.sin(theta), math.cos(theta), 0],
                   [0, 0, 1]])
    return RZ

  • FANUC机械臂转换矩阵相关程序:
'''
机械臂转换矩阵相关
'''
def WPR2R(w,p,r):
    '''
    定角旋转WPR转为旋转矩阵(角度)
    '''
    R = Rz(r/180*math.pi)@Ry(p/180*math.pi)@Rx(w/180*math.pi)
    return R
def FANUC2trans(x,y,z,w,p,r):
    '''
    FANUC转换矩阵(mm,角度,wpr)
    '''
    t = np.zeros((4, 4))
    t[0:3, 0:3] = WPR2R(w,p,r)
    t[:,3] = x,y,z,1
    t[3,0:3] = 0,0,0
    return t

4.多视角拼接

  • 初始化一个点云pcd_all用来保存完成坐标变换后的点云
  • 为了与转换矩阵相匹配,为点云添加一列:
pcd_np = np.concatenate((pcd_np, np.expand_dims(np.ones(pcd_np.shape[0]), axis=1)), axis=1)
  • 点云左乘相机外参转换矩阵,再左乘机械臂转换矩阵,即得到点云在机械臂基座的坐标
  • 最终效果:
    在这里插入图片描述在这里插入图片描述

5.完整代码

import numpy as np
import math
import open3d as o3d
from Transformations import xyzrpw_to_H

'''
旋转矩阵相关
'''
def Rx(theta):
    '''
    绕X轴旋转矩阵
    '''
    RX = np.array([[1, 0, 0],
                   [0, math.cos(theta), -1*math.sin(theta)],
                   [0, math.sin(theta), math.cos(theta)]])
    return RX
def Ry(theta):
    '''
    绕Y轴旋转矩阵
    '''
    RY = np.array([[math.cos(theta), 0, math.sin(theta)],
                   [0, 1, 0],
                   [-1*math.sin(theta), 0, math.cos(theta)]])
    return RY
def Rz(theta):
    '''
    绕Z轴旋转矩阵
    '''
    RZ = np.array([[math.cos(theta), -1*math.sin(theta), 0],
                   [math.sin(theta), math.cos(theta), 0],
                   [0, 0, 1]])
    return RZ

'''
机械臂转换矩阵相关
'''
def WPR2R(w,p,r):
    '''
    定角旋转WPR转为旋转矩阵(角度)
    '''
    R = Rz(r/180*math.pi)@Ry(p/180*math.pi)@Rx(w/180*math.pi)
    return R
def FANUC2trans(x,y,z,w,p,r):
    '''
    FANUC转换矩阵(mm,角度,wpr)
    '''
    t = np.zeros((4, 4))
    t[0:3, 0:3] = WPR2R(w,p,r)
    t[:,3] = x,y,z,1
    t[3,0:3] = 0,0,0
    return t

'''
相机外参
'''
def get_waican(x,y,z,rx,ry,rz):
    '''
    获取外参转换矩阵,mm,角度,欧拉角xyz
    '''
    R = Rx(rx/180*math.pi)@Ry(ry/180*math.pi)@Rz(rz/180*math.pi)
    t = np.zeros((4, 4))
    t[0:3, 0:3] = R
    t[:, 3] = x, y, z, 1
    t[3, 0:3] = 0, 0, 0
    return t

if __name__ == '__main__':

    root = 'datasFANUC'

    #外参转换矩阵
    # t_waican = get_waican(70.609, 264.977, -33.942, -0.80, 0.73, 147.95+10)
    t_waican = FANUC2trans(70.5, 269.927, -33.947, -0.85, 0.78, 147.95)
    print(t_waican)
    #t_waican = xyzrpw_to_H(np.array([70.5, 269.927, -33.947, -0.85, 0.78, 147.95]))
    print('外参转换矩阵:')
    print(t_waican)

    '''
    文本文件读取机械臂姿态
    索引,文件名(无后缀),X,Y,Z(mm),W,P,R(角度)
    '''
    flag = 1
    robot_data = root + '/datas.txt'
    f = open(robot_data)
    for line in f.readlines():
        line = line.strip('\n').split(',')
        print('索引:', line[0])
        file_data = line[1]
        print('处理文件:', file_data)
        # 转换矩阵
        line = line[2:]
        line = [float(i) for i in line]
        x,y,z,w,p,r = line
        t_robot = FANUC2trans(x,y,z,w,p,r)
        #print('机器人转换矩阵:', t_robot)
        #t_robot = xyzrpw_to_H(np.array([x,y,z,w,p,r]))
        t = t_robot@t_waican
        print(t)

        # 读取点云
        pcd = o3d.io.read_point_cloud(root + '/' + file_data + '.ply')
        pcd.paint_uniform_color([1.0, 0, 0])
        # o3d.visualization.draw_geometries([pcd])
        pcd_np = np.array(pcd.points) * 1000
        pcd_np = np.concatenate((pcd_np, np.expand_dims(np.ones(pcd_np.shape[0]), axis=1)), axis=1)
        #print(pcd_np.shape)
        pcd_np = pcd_np.T
        pcd_np = t@pcd_np
        pcd_np = pcd_np.T



        # 使用第一个点云初始化最终点云
        if flag:
            pcd_all = pcd_np
            flag = 0
        else:
            pcd_all = np.concatenate((pcd_all, pcd_np))
            #print(pcd_all.shape)
            #print(pcd_all)
            #break

    pcd_show = o3d.geometry.PointCloud()
    pcd_show.points = o3d.utility.Vector3dVector(pcd_all[:, :3])
    pcd_show.paint_uniform_color([1.0, 0, 0])

    # zero = o3d.geometry.PointCloud()
    # zero.points = o3d.utility.Vector3dVector(np.zeros((1, 3)))
    # zero.paint_uniform_color([0, 1.0, 0])

    #pcd = o3d.io.read_point_cloud('datasFANUC/' + 'point_cloud_00000' + '.ply')
    #pcd_np = np.array(pcd.points) * 1000
    #pcd.points = o3d.utility.Vector3dVector(pcd_np)
    #pcd.paint_uniform_color([0, 1.0, 0])
    o3d.visualization.draw_geometries([pcd_show])
    # zero,

6.调包获得转换矩阵

  • Transformations下载地址
from Transformations import xyzrpw_to_H
t_waican = xyzrpw_to_H(np.array([70.5, 269.927, -33.947, -0.85, 0.78, 147.95]))
  • 注意:包里使用的是欧拉角旋转,计算顺序和FANUC的定角旋转是相反的,所以使用的是xyzrpw_to_H函数而不是xyzwpr_to_H

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零代码+分布式微服务架构打造新一代一站式服务集成平台

目 录 01 项目背景 02 普元ESB产品介绍 03 新版本功能特性 04 应用案例‍‍‍‍ 05 展望与发展 01 项目背景 企业在实现数字化转型的过程中,随着信息化程度的提高,越来越多的企业开始采用微服务架构来构建自己的业务系统,各种系统之间的集成、数据共享…

k8s上对Pod的管理部分详解

目录 一.Pod结构介绍 1.user container 2.pause 二.Pod工作形式介绍 1.自主式pod 2.控制器管理下的pod 三.对Pod的操作介绍 1.run/apply -f/create -f运行pod 2.get查看pod信息 3.exec操作运行中的pod (1)进入运行中的pod (2&…

Linux RPM包安装、卸载和升级

我们以安装 apache 程序为例。因为后续章节还会介绍使用源码包的方式安装 apache 程序,读者可以直观地感受到源码包和 RPM 包的区别。 RPM包默认安装路径 通常情况下,RPM 包采用系统默认的安装路径,所有安装文件会按照类别分散安装到表 1 所…

阿里云付费用户破100万 用户规模亚洲最大

导读阿里巴巴集团公布2018财年第一季度财报,阿里云达到一个重要里程碑,云计算付费用户数量首次超过100万,成为亚洲首家达到百万级用户规模的云计算公司。同时,企业级市场被云计算人工智能等新技术全面激活,推动该季度营…

Stable Diffusion:最先进的文本生成图像模型

稳定扩散 生成式 AI 技术正在迅速发展,现在可以简单地根据文本输入生成文本和图像。Stable Diffusion 是一种文本到图像模型,使您能够创建逼真的应用程序。 扩散模型通过学习去除添加到真实图像中的噪声进行训练。这种降噪过程会产生逼真的图像。这些模…

【研究】Splunk 字段是否被加工过

1: 背景: 最近用户有个疑问,就是有些字段的输出有点问题,不确定是否被加工过。 2: 查找问题: index=abc sourcetype=def123 发现字段: city_shanghai 的输出可能有点问题。 3: 排查问题: 先去这个splunk search head cluster 的页面: server 的查找如下: 登入so1 s…

【Linux系统概念】

Linux系统概念 1 用户1.1 su和sudo1.1.1 /etc/sudoers 1.21.3 2345 1 用户 1.1 su和sudo 为什么会有su和sudo命令? 在实际工作当中需要在Linux不同用户之间进行切换。 root用户权限最高很多时候需要root用户才能执行一些关键命令。所以需要临时切换为root用户。工…

【C++】智能指针(一)

这篇文章介绍下C的智能指针,当然,可能没有你想的那么智能。 为什么需要智能指针1 void remodel(string& str) {string* ps new string(str);str *ps;return; }这里不讨论这个函数有没有意义,在这段代码中,很明显&#xff…

数据分析实战 | SVM算法——病例自动诊断分析

目录 一、数据分析及对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据准备 七、模型训练 八、模型应用及评价 一、数据分析及对象 CSV文件——“bc_data.csv” 数据集链接:https://download.csdn.net/download/m0_70452407/88…

Linux操作系统下对c语言程序的编译和执行过程gcc,编译链接过程

目录 1.gcc,g,gdb安装 2.gcc分布编译链接 3.编译链接过程 4.执行 4.1 如何执行 4.2 两步执行与一步执行 4.3 多文件的编译执行 1.gcc,g,gdb安装 命令行写gcc,g,gdb根据提示安装:sudo apt install gcc/g/gdb 2.gcc分布编译链接 (1)预编译: gcc -E main.c -o main.i (2)…

关于el-table+el-input+el-propover的封装

一、先放图片便于理解 需求: 1、el-input触发focus事件,弹出el-table(当然也可以为其添加搜索功能、分页) 2、el-table中的复选共能转化成单选共能 3、选择或取消的数据在el-input中动态显示 4、勾选数据后,因为分页过多,原先选好…

VEINS_CARLA代码详解

VEINS_CARLA代码详解 examples/veins_carlaprotosrc/veins_carla/appveins_carla/src/veins_carla/mobilityveins_carla/src/veins_carla/nodesveins_carla/src/veins_carla/proto 基于GPT-3.5 examples/veins_carla 从examples/veins_carla开始: CarlaExampleS…

P5906 【模板】回滚莫队不删除莫队

这一题,虽说在洛谷标的是模板题,但可能没有“历史研究”那一题更加模板。 这一题相对于回滚莫队的模板题,可能在回滚的处理上稍微复杂了一点。对于回滚莫队就不多解释了,可以看一下 回滚莫队模板题 这一篇博客,稍微简单…

PHP 服装销售管理系统mysql数据库web结构layUI布局apache计算机软件工程网页wamp

一、源码特点 PHP 服装销售管理系统是一套完善的web设计系统mysql数据库 ,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 php服装销售管理系统1 二、功能介绍 (1)员工管理:对员工信息…

第十八章 Swing 程序设计

目录 概述 Swing常用窗体 JFrame 窗体 JDialog 对话框 JOptionPane 小型对话框 1.自定义对话框 2.确认框 3.输入框 4.通知框 常用布局管理器 null绝对布局 FlowLayout 流布局管理器 BorderLayout 边界布局管理器 GridLayout 网络布局管理器 常用面板 JPa…

一文图解爬虫(spider)

—引导语 互联网(Internet)进化到今天,已然成为爬虫(Spider)编制的天下。从个体升级为组合、从组合联结为网络。因为有爬虫,我们可以更迅速地触达新鲜“网事”。 那么爬虫究竟如何工作的呢?允许…

lv11 嵌入式开发 ARM指令集上 5

1 导学 1.1 指令集 指令 能够指示处理器执行某种运算的命令称为指令(如加、减、乘 ...) 指令在内存中以机器码(二进制)的方式存在 每一条指令都对应一条汇编 程序是指令的有序集合 指令集 处理器能识别的指令…

翻转二叉树(C++解法)

题目 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 给你一棵二叉树的根节点 root ,翻转这棵二叉树&…

Harbor了解及部署

Harbor 无论是使用Docker-distribution去自建仓库,还是通过官方镜像跑容器的方式去自建仓库,通过前面的演示我们可以发现其是非常的简陋的,还不如直接使用官方的Docker Hub去管理镜像来得方便,至少官方的Docker Hub能够通过web界…

openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库

文章目录 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库120.1 密态等值查询概述120.2 使用gsql操作密态数据库 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库 120.1 密态等值查询…