从零实现无序抓取(四)如何获取点云位姿估计真值

本文介绍了如何利用Bullet物理引擎进行3D仿真模拟,包括安装pybullet、导入模型、设置重力等步骤,并展示了如何通过仿真获取RGB图像和深度图像。同时,讲解了如何将深度图像转换为点云数据,为无序抓取等应用场景提供数据支持。
摘要由CSDN通过智能技术生成

前言

这是一章预告。
上一章在进行点云位姿估计时,我们利用PCL库对原始点云进行了一个人工设定的变换矩阵,这个变换矩阵可以作为位姿估计的真值。但是这种方式只能很简单地将某个原始点云整体进行变换。也就是只能生成下图这种变化。
在这里插入图片描述
但是我们的实际的位姿估计算法不可能只在这种简单的场景下应用。一般来说,具体的抓取场景应该是有多个目标相互堆叠存在于场景中的。类似这样。
在这里插入图片描述
现实中我们可以利用点云相机采集这个场景的点云,然后估计目标的位姿,但是我们难以通过测量的方式得到每个零件的6DoF位姿,也就是说我们很难得到场景中目标的真值,没有真值我们就无法评价算法的误差,不能定量的评价误差,我们就没办法评估不同算法之间的精度,也就没办法发论文。那么,如何获得目标真值位姿呢?可以采用仿真的方式生成与实际场景类似的仿真数据。
我在这里采用了bullet物理仿真引擎进行了自由落体的仿真模拟。
先放上一段效果:

bullet自由落体仿真

然后是点云模拟的结果:
在这里插入图片描述

一、利用bullet进行自由落体仿真

Bullet是一个开源的物理模拟计算引擎,世界三大物理模拟引擎之一(另外两种是Havok和PhysX)。广泛应用于游戏开发和电影制作中。Bullet也是AMD开放物理计划成员之一。持Windows、Linux、MAC、Playstation3、XBOX360、Nintendo Wii。Bullet也整合到了Maya和Blender 3D中。

1.1 安装pybullet

现在Bullet已经可以很好的支持python了
安装方式简单粗暴直接
pip install pybullet
验证一下是否成功,打开命令行,输入

python -m pybullet_envs.examples.enjoy_TF_AntBulletEnv_v0_2017may

可以看见一只正在走路的四脚蜘蛛
在这里插入图片描述

1.2 导入模型

先看一个例子,如何初始化引擎并导入已有的模型。

import pybullet as p
import pybullet_data

# 连接引擎
_ = p.connect(p.GUI)
# 不展示GUI的套件
p.configureDebugVisualizer(p.COV_ENABLE_GUI, 0)

# 添加资源路径
p.setAdditionalSearchPath(pybullet_data.getDataPath())

planeUid = p.loadURDF("plane.urdf", useMaximalCoordinates=True)  # 加载一个地面
trayUid = p.loadURDF("tray/traybox.urdf", basePosition=[0, 0, 0])  # 加载一个箱子,设置初始位置为(0,0,0)

# 开始渲染
while True:
    p.stepSimulation()

代码结果
在这里插入图片描述
代码不详细解释了,有兴趣可以去看看pybullet官网,或者建议看官方的教程进行入门学习。
链接:https://pan.baidu.com/s/1mwyAjckm1IR6F-I-trU_og
提取码:w2uh

1.3 urdf文件

代码中比较重要的部分,这两句是用来导入urdf文件的,这个文件需要自己编写,里面包含了你要加载的模型的视觉属性和碰撞属性。

planeUid = p.loadURDF("plane.urdf", useMaximalCoordinates=True)  # 加载一个地面
trayUid = p.loadURDF("tray/traybox.urdf", basePosition=[0, 0, 0])  # 加载一个箱子,设置初始

我们进入到bullet的资源文件路径里面找一下这两个文件,看看是什么样子

print(pybullet_data.getDataPath())

‘D:\Anaconda\Anaconda\envs\bullet\lib\site-packages\pybullet_data’
找到traybox.urdf文件,打开后可以看到

<robot name="tabletop">
  <link name="base_link">
    <inertial>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <mass value="0"/>
      <inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="tray_textured.obj" scale="5 5 5"/>
      </geometry>
      <material name="tray_material">
        <color rgba="1 1 1 1"/>
      </material>
    </visual>
     <collision>
      <origin rpy="0 0 0" xyz="0 0 0.005"/>
      <geometry>
	 			<box size=".6 .6 .02"/>
      </geometry>
    </collision>
     <collision>
      <origin rpy="0 0.575469961 0" xyz="0.25 0 0.059"/>
      <geometry>
	 			<box size=".02 .6 .15"/>
      </geometry>
    </collision>
		<collision>
      <origin rpy="0 -0.575469961 0" xyz="-0.25 0 0.059"/>
      <geometry>
	 			<box size=".02 .6 .15"/>
      </geometry>
    </collision>
    <collision>
      <origin rpy="0.575469961 0 0" xyz="0 -0.25 0.059"/>
      <geometry>
	 			<box size=".6 .02 .15"/>
      </geometry>
    </collision>
    <collision>
      <origin rpy="-0.575469961 0 0" xyz="0 0.25 0.059"/>
      <geometry>
	 			<box size=".6 .02 .15"/>
      </geometry>
    </collision>

  </link>
</robot>

因为我们要导入的是一个单独的零件,所以不存在有多个link joint(不理解请返回阅读官方的教程),重点看

    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="tray_textured.obj" scale="5 5 5"/>
      </geometry>
      <material name="tray_material">
        <color rgba="1 1 1 1"/>
      </material>
    </visual>

这部分描述了物体的视觉属性,mesh filename就是我们自己的零件对应的.obj文件,如何画自己的.obj文件,可以参照我的另一篇从零实现无序抓取(二)制作属于自己的点云数据,此外可以这个里面还可以定义他的rgba颜色属性,还有material材料属性(非必须,这个文件就没有定义)。

然后另一个部分

    <collision>
      <origin rpy="-0.575469961 0 0" xyz="0 0.25 0.059"/>
      <geometry>
	 			<box size=".6 .02 .15"/>
      </geometry>
    </collision>

描述了模型的碰撞属性,官方这个文件是自己设置了一个box类型的碰撞属性。我们也可以设置成自己的obj,只需要把这一部分的内容和视觉属性部分保持一致就可以了。

1.4 制作自己的urdf文件

这里放上我自己写的一个urdf文件,part1.urdf

<robot name="blob000">
  <link name="random_obj_000">
    <contact>
      <lateral_friction value="1.0"/>
      <rolling_friction value="0.0"/>
      <inertia_scaling value="3.0"/>
      <contact_cfm value="0.0"/>
      <contact_erp value="1.0"/>
    </contact>
    <inertial>
      <origin rpy="0 0 0" xyz="0.6 0.05 0.4"/>
      <mass value="1"/>
      <inertia ixx="1" ixy="1" ixz="1" iyy="1" iyz="1" izz="1"/>
    </inertial>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="part1.obj" scale="0.01 0.01 0.01"/>
      </geometry>
      <material name="blockmat">
        <color rgba="0.5 0.5 0.5 1"/>
      </material>
    </visual>
    <collision>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <mesh filename="part1.obj" scale="0.01 0.01 0.01"/>
      </geometry>
    </collision>
  </link>
</robot>

这个文件就是将part1这个模型根据part1.obj进行了视觉属性和碰撞属性的定义,把这个模型加载后可以得到。
在这里插入图片描述

1.5 添加重力

现在只是把模型加载好,但是还没有设置重力,很简单

p.setGravity(0,0,-10)

把这句话加进去就行了。

最终的仿真效果,这里我同时加载了好几个模型,并让他们从不同的初始位置开始下落。
在这里插入图片描述

二、在bullet中采集RGB图和深度图

现在我们有了场景模型,那如何获得点云呢?bullet好像不能直接生成点云,他只能得到场景的点云图和深度图,后期的点云图需要用深度图合成出来。

width, height, rgbImg, depthImg, segImg 
= p.getCameraImage(width=1080, height=720,projectionMatrix=projectionMatrix)

获取深度图的方式也很简单,在渲染中加入这句话就行了。
返回的depthImg为numpy格式,自己把它保存下来就行了。

三、将深度图转换为点云图

有了深度图,我们还需要将深度图转换为点云数据,这里需要先获取相机的参数。

projectionMatrix = p.computeProjectionMatrixFOV(
    fov=50.0,               # 摄像头的视线夹角
    aspect=1.0,
    nearVal=0.001,            # 摄像头焦距下限
    farVal=20,               # 摄像头能看上限
)
print(projectionMatrix)

输出结果:
(2.1445069313049316, 0.0, 0.0, 0.0,
0.0, 2.1445069313049316, 0.0, 0.0,
0.0, 0.0, -1.0000998973846436, -1.0,
0.0, 0.0, -0.00200009997934103, 0.0)
这个矩阵就是openGL里面的投影矩阵了,不做详细解释了,可以自行去看看。
然后用深度图在这个矩阵上做变换,就可以得到点云数据了,这里我用matlab做了结果的可视化。
在这里插入图片描述

要求两个点云之间的重叠真值,可以使用以下步骤: 1. 预处理点云:首先,对两个点云进行预处理。例如,使用滤波算法去除噪声点,对点云进行降采样,以减少计算复杂度,并提高匹配质量。 2. 特征点提取:从两个点云中提取特征点。特征点可以是显著的几何特征,如角点、边缘点等。这些特征点可以作为后续的点云匹配算法的输入。 3. 点云匹配算法:使用点云匹配算法来计算两个点云之间的配准变换。常见的点云匹配算法包括最近邻搜索、Iterative Closest Point(ICP)等。这些算法可以计算两个点云之间的刚体变换矩阵,将一个点云对准到另一个点云。 4. 重叠区域计算:根据匹配结果,可以通过计算两个点云之间的重叠区域来求得重叠真值。重叠区域可以定义为一个区域,其中两个点云的点密度较高并且彼此之间的距离较近。可以使用基于距离或密度的算法,如基于KD树、半径近邻搜索等方法来计算重叠区域。 5. 评估指标计算:可以使用一些评估指标来量化两个点云之间的重叠度。例如,可以计算重叠区域内点的比例,或者计算重叠区域的IoU(Intersection over Union)等。 通过以上步骤,可以求得两个点云之间的重叠真值,并用评估指标进行量化。这样可以帮助我们了解两个点云的匹配质量,并进一步应用于点云配准、三维重建等应用中。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值