当您获得本文档时,可至 RVS 开发者社区下载 model_matching.zip 3D 模型匹配教程配套数据。解压后其内容应包括:
其中本案例中需要用到的有:
-
create_model.xml:将模型文件生成模板点云并进行点云预处理及保存。
-
RVSCommonGroup:常用的 Group 组,根据需要加载。
-
model.pcd:该文件为 create_model.xml 运行后保存的点云文件。
-
match_model.xml:用于离线模板匹配,使用时需要更新 ReadDirectoryNames 算子中离线数据的路径和 LoadModelCloud 算子中的模板点云文件。使用时先点击交互面板中 start 按钮启动工程后,再点击 iterate 按钮迭代 test_data 中的离线数据。
-
test_data:用于模板匹配数据的加载,使用时请注意路径正确。
-
workpiece.obj:用于create_model.xml中 Load-Polydata 算子加载的 3D 模型文件。(RVS支持的模型文件格式有:*.ply *.stl *.obj *.gltf *.glb。如果当前拥有的模型文件格式不符,需要提前完成转换。)
案例所有使用到的文件均保存在 model_matching 下,请放在 RVS 安装目录下的 projects 内运行。如:
说明:若在windows版本,请放在 RVS 安装目录下运行即可。
说明:如不想调整 XML 中的文件路径。可以将 unstacking_runtime 重命名为 runtime 。
注:本文档所使用RVS软件版本为1.5.236,若在使用中出现问题或版本不兼容问题,请及时与我们反馈,发送邮件 rvs-support@percipio.xyz !
模板点云生成
在模板匹配流程中,需要用到模板点云。在拥有 3D 模型文件的前提下,我们需要根据 3D 模型生成模板点云,并对点云进行预处理、调整并保存。本章节主要介绍如何进行生成模板点云,包括以下步骤:
-
网格采样:根据给定的 3D 模型创建点云。
-
点云预处理:划分点云中合适的工作区域。
-
调整点云:调整模板点云物体面与坐标系。
网格采样
加载 3D 模型文件,使用 MeshSampling 算子将其转化为点云。
操作步骤:
说明:可直接使用 model_matching/ 路径下的 create_model.xml 进行模板点云生成,也可按照以下步骤自行连接 xml 。
-
新建工程项目 create_model.xml 。
-
添加 Trigger、Load 、MeshSampling 算子至算子图。
-
设置算子参数。
-
设置 Load 算子参数:
-
type → PolyData
-
filename → → workpiece.obj (如果是直接加载已有的 create_model.xml ,注意文件路径)
-
surface → 可视
-
-
设置 MeshSampling 算子参数:
-
sample_points → 10000
-
cloud → 可视 → 90
-
-
-
连接算子。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
结果如下图所示。在3D视图中,显示灰白色的为模型,绿色为转化后的点云。
点云预处理
将 3D 模型转化为点云后,对点云进行预处理。根据模板匹配的作业要求,需切割点云,只保留模型点云的上表面作为工作区域。
操作步骤:
-
添加 Emit 、CloudSegment 算子至算子图。
-
设置算子参数。
-
设置 Emit 算子参数:
-
type → Cube
-
pose → 0.101468 0.048794 -0.072353 1.253140 1.543760 1.253250
-
width → 0.3
-
height → 0.3
-
depth → 0.2
-
cube → 可视
-
-
设置 CloudSegment 算子参数:
-
type → CropboxSegment
-
mode → intersection
-
cloud → 可视 → 0
-
说明:CloudSegment 算子用于根据给定的立方体切割出所需要点云。
-
-
连接算子。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
结果如下分别展示了点云切割前中后 3D 视图中显示的点云。左图为 MeshSampling 算子的点云可视化结果。中间图为 MeshSampling 和 Emit 算子的可视化结果。右图为 CloudSegment 算子的点云可视化结果。
调整点云
模板匹配算子( ICP 算子)要求输入的模板点云与实际来料物体点云的 Oxy 平面平行,且模板点云中心在 RVS 的 3D 世界坐标系的原点。 由于实际来料物体点云位于机器人坐标系下,而机器人坐标系与 RVS 中的 3D 世界坐标系重合。因此,将模板点云进行空间变换,使得其姿态的 Oxy 平面平行于 RVS 3D 世界坐标系的 Oxy 平面,且点云中心在 RVS 的 3D 世界坐标系的原点,即可满足 ICP 算子的输入要求。
操作步骤:
步骤一:获得模板点云最小包围立方体及其中心点位姿
-
添加 MinimumBoundingBox 、Emit 算子至算子图。
-
设置算子参数:
-
设置 MinimumBoundingBox 算子参数:
-
type → ApproxMVBB
-
point_samples → 500
-
box → 可视
-
box_pose → 可视
-
说明:MinimumBoundingBox 算子用于获取点云中心点。
-
设置 Emit 算子参数:
-
算子名称 → EmitPose
-
type → pose
-
pose → 0 0 0 0 0 0
-
-
-
连接算子。
说明:EmitPose 算子生成的 pose 数据连接 MinimunBoundingBox 算子左侧的 ref_pose 端口,用于将输入 cloud 计算出的最小包围立方体 Hight-Width-Depth 与 ref_pose X-Y-Z 进行匹配。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
如下图所示,此时得到最小包围立方体及其中心点位姿。该立方体的中心点位姿视为模板点云中心点位姿。
说明:此时 Pose 的中心点可以作为模板点云的中心点,但是该 Pose 的 Oxy 平面并未与实际来料物体姿态的 Oxy 平面平行,所以需要将当前的 pose 绕着其 Y 轴旋转 -90°。
步骤2:旋转模板点云中心点位姿,使得其 Oxy 平面与实际来料物体姿态的 Oxy 平面平行
-
添加 Emit 、Transform 算子至算子图。
-
设置算子参数。
-
设置 Emit 算子参数:
-
算子名称 → RotY90
-
type → Pose
-
pose → 0 0 0 0 -1.5708 0
-
pose → 可视
-
-
设置 Transform 算子参数:
-
算子名称 → RotY90
-
type → Pose
-
-
-
连接算子。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
如下图所示,展示了模板姿态 Oxy 转换的过程。左图为原始 pose ,中间图为原始 pose 和生成 pose ,右图为旋转后的 pose。
说明:将当前模板姿态的 Oxy 平面与实际来料物体姿态的 Oxy 平面保持平行。之后需要将模板点云的中心移动到 RVS 中的 3D 世界坐标系的原点。
步骤3:将模板点云中心点移动至 3D 世界坐标系的原点
-
添加 AdjustPose 、Transform 算子至算子图。
-
设置算子参数。
-
设置 AdjustPose 算子参数:type → InvertPose
-
设置 Transform 算子参数:
-
算子名称 → TransformPointCloud
-
type → PointCloud
-
cloud → 可视 → 60
-
-
-
连接算子。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
如下图所示。展示了点云转换前后对比,3D 视图中黄色点云为算子 TransformPointCloud 转换后的点云。此时转换后的点云的中心在 RVS 中的 3D 世界坐标系的原点上。
说明:可以单次运行一个 Emitpose(0,0,0,0,0,0)验证转换后点云中心是否在3D 世界坐标系的原点上。可以看出云的中心已经移动到 RVS 中的 3D 世界坐标系的原点。
保存点云
根据调整点云的流程后,我们获得了点云中心在RVS 中的 3D 世界坐标系原点的模板点云,现在保存该模板点云,以便我们在模板匹配中使用。
操作步骤:
-
添加 Save 算子至算子图。
-
设置算子参数。如下图所示。
-
设置 Save 算子参数:
-
type → PointCloud
-
filename → model.pcd
-
-
-
连接算子。
-
点击 RVS 运行按钮,并触发 Trigger 算子。
运行结果
此时可以在 runtime 目录下看到保存的 “model.pcd” 。
模板匹配
在创建好模板点云后,我们可以进行模板匹配工作。本案例中主要依赖于 ICP 算子进行模板匹配,ICP 算子需要准备模板点云(source_cloud)、目标点云(target_cloud)、两个点云之间的转换关系的初始值 initial_pose 。 我们需要确保 initial_pose 基本准确,然后 ICP 算子就是在这个 initial_pose 的基础上进一步的微调从而获得最终的 result_pose ,使得模板点云根据 result_pose 进行空间变换以后能够和真实点云达到重合效果。
本章节主要介绍如何进行模板匹配,包括以下步骤:
-
模板点云准备:加载模板点云。对点云进行稀疏化处理,提高算子执行效率。
-
目标点云准备:本案例有多组离线测试数据,用 Foreach-String 算子遍历读取目标点云名称,并用 load 算子加载对应目标点云。
-
目标点云预处理:去除目标点云中的背景点云(如地面),并对点云进行降采样,提高后续算子的执行效率。
-
初始推测值准备:给定多组初始推测值,得到最优解。
-
模板匹配:ICP 算子获得 result_pose ,将模板点云根据该 pose 进行空间变换后与目标点云重合。
模板点云准备
加载模板点云。对点云进行稀疏化处理,提高算子执行效率。
操作步骤:
说明:可直接使用 model_matching/ 路径下的 match_model.xml 进行模板匹配。也可按照以下步骤自行连接 xml 。
-
新建工程项目match_model.xml。(可直接导入 model_matching/RVSCommonGroup 目录下的 LoadModelCloud.group,注意文件路径)
-
在算子图中创建一个新的 Group 。添加 Trigger、Load、Emit、DownSampling 算子。
-
设置算子参数。
-
设置 Group 参数:算子名称 → LoadModelCloud
-
设置 Trigger 算子参数:type → InitTrigger
说明:用于自动触发 LoadModelCloud 算子和 Emit 算子。
-
设置 Load 算子参数:
-
算子名称 → LoadModelCloud
-
type → PointCloud
-
filename → model.pcd ( 已保存的 model.pcd 的文件路径,注意文件路径 )
-
cloud → 可视 → 90
-
-
设置 Emit 算子参数:
-
type → Pose
-
pose → 0 0 0 0 0 0
-
pose → 可视
说明:生成基于RVS 3D世界坐标原点Pose(0,0,0,0,0,0)。
-
-
设置 DownSampling 算子参数:
-
算子名称 → DownSampling_model
-
type → DownSample
-
leaf_x → 0.002
-
leaf_y → 0.002
-
leaf_z → 0.002
说明:表示在0.002m * 0.002m * 0.002m的空间尺度内仅取一个点。
-
-
-
连接算子。
-
点击 RVS 运行按钮。
运行结果
如下图所示,在 3D 视图中显示加载的模板点云和生成的原点 pose,此时的原点pose也是点云的中心点。
目标点云准备
加载测试数据,本案例有多组离线数据,因此需要使用 Foreach-String 算子进行遍历加载目标点云文件。
操作步骤:
-
添加 Trigger(2个)。
-
设置 Trigger 算子参数:
-
算子名称 → start
-
Trigger →
-
-
设置 Trigger_1 算子参数:
-
算子名称 → iterate
-
Trigger →
-
-
-
在算子图中创建一个新的 Group 。(可以直接导入 model_matching/RVSCommonGroup 目录下的 LoadTargetCloud.group,注意文件路径)
-
添加 DirectoryOperation、Foreach、Emit(2个)、Load(2个)算子。
-
设置 Group 参数:算子名称 → LoadTargetCloud
-
设置 DirectoryOperation 算子参数:
-
type → ReadDirectory
-
directory → test_data (如果您是直接加载已有的match_model.xml,注意文件路径)
说明:这步操作用于加载离线数据文件夹。
-
-
设置 Foreach 算子参数:type → String
-
设置 Emit 算子参数:
-
算子名称 → image_name
-
type → string
-
string → /rgb.png
-
-
设置 Load 算子参数:
-
算子名称 → LoadImage
-
type → Image
-
image → 可视
-
-
设置 Emit_1 算子参数:
-
算子名称 → cloud_name
-
type → string
-
string → /cloud.pcd
-
-
设置 Load_1 算子参数:
-
算子名称 → LoadPointCloud
-
type → PointCloud
-
cloud → 可视
-
-
-
在交互面板中添加 2 个输入工具——“按钮”控件,鼠标双击重新命名→ start 和 iterate 。鼠标中键点击按钮,选择同名的曝光属性绑定。
-
连接算子。
-
点击 RVS 运行按钮。点击面板上的
start
按钮时,触发后续算子。当点击面板上iterate
按钮时,遍历 test_data 文件夹中的离线数据。
运行结果
如下所示,在 2D 视图中显示当前遍历的图像,在 3D 视图中显示当前遍历的点云。
点云预处理
加载测试点云数据后,需要剔除背景点云,筛选出工作区域。对点云进行稀疏化处理,提高算子执行效率。
操作步骤:
步骤1:裁剪点云,筛选出工作区域
-
添加 Emit 、CloudSegment 算子至算子图。
-
设置算子参数。
-
设置 Emit 算子参数:
-
算子名称 → EmitCube
-
type → Cube
-
pose → -0.126006 -0.085611 0.621984 -3.141590 -3.117050 3.035830
-
width → 0.5
-
height → 0.5
-
depth → 0.2
-
cube → 可视
-
-
设置 CloudSegment 算子参数:
-
type → CropboxSegment
-
cloud → 可视 → 90
说明:CloudSegment 算子用于根据给定的立方体切割出所需要的点云。
-
-
-
连接算子 。
-
点击 RVS 运行按钮。点击面板上
start
按钮。
运行结果
如下图所示,下图为裁剪框前后的点云。左图为切割前点云,中间图为生成的 Cube,右图为切割后点云(绿色部分)。
步骤2:点云降采样
-
添加 DownSampling 算子至算子图。
-
设置算子参数。
-
设置 DownSampling 算子参数:
-
算子名称 → DownSampling_cloud
-
type → DownSample
-
leaf_x/leaf_y/leaf_z → 0.002
-
cloud → 可视 → 90
说明:将 DownSampling 算子的 leaf_x、leaf_y、leaf_z 指定 xyz 轴方向点云重采样间距,此处设置为0.002m,表示在 0.002m * 0.002m * 0.002m的空间尺度内仅取一个点。
-
-
连接算子。
-
点击 RVS 运行按钮,点击面板上的
start
按钮。
运行结果
如下图所示,下图为降采样前后点云对比。左图为降采样前点云,右图为降采样后点云。
初始推测值准备
模板匹配计算的是模板点云到目标点云的转换 Pose 。在计算转换 Pose 前,需要给定初始评估值。评估值同真实值越接近,则越容易获得稳定的匹配结果。通过 MinimumBoundingBox 算子获得输入的目标点云的中心位姿 Pose,作为初始推测值。但由于目标实际点云的长短边分别沿着 Pose 的 x 轴或 y 轴方向,所以模板点云转换后的长短边也需同实际点云的长短边彼此平行。
目标点云 Oxy 和模板点云 Oxy 平面平行,但可能出现标点云 X(Y)轴转化成目标点云 Y(X)轴。因此,需根据 MinimumBoundingBox 算子输出的 pose ,沿着其 z 轴依次旋转 90 度总共获得 4 个 pose ,全部作为初始推测值,则可保证 4 个 pose 中必有一个接近真实值。
操作步骤:
-
添加 MinimumBoundingBox 、Emit 、GenerateSamplePose 算子至算子图。
-
设置算子参数。
-
设置 MinimumBoundingBox 算子参数:
-
type → SimpleMVBB
-
box → 可视 (显示计算出的最小立方体包围框 )
-
box_pose → 可视 (显示计算出包围框的中心点)
-
-
设置 Emit 算子参数:
-
算子名称 → EmitPose
-
type → Pose
-
pose →0 0 0 0 0 0
-
-
设置 GenerateSamplePose 算子参数:
-
type → BoxGridSample
-
min_position → 0 0 0 0 0 -3.141593
-
max_position → 0 0 0 0 0 1.5708
-
step_yaw → 4
-
pose_list → 可视
-
-
-
连接算子。
-
点击 RVS 运行按钮,点击面板上的
start
按钮。
运行结果
下图为 MinimumBoundingBox 和 GenerateSamplePose 在 3D 视图中的显示。左图为 MinimumBoundingBox 算子结果。右图为 GenerateSamplePose 算子结果。
模板匹配
经过上述四个步骤后,已经准备好了模板点云(source_cloud)、目标点云(target_cloud)、4组初始值initial_pose,此时,我们需要使用 ICP 算子获得最优变换 result_pose ,将模板点云根据该 pose 进行空间变换后与目标点云重合。
操作步骤:
-
添加 ICP 、Transform 算子至算子图。
-
设置算子参数
-
设置 ICP 算子的属性参数:
-
max_correspondence_distance → 0.005
说明:该值表示目标点云与模板点云匹配时两个匹配点之间的最大空间距离。超过该距离认为该组匹配点无效。过多的无效匹配意味当前的匹配效果很差。
-
ransac_outlier_rejection_threshold → 0.15
说明:该值表示去除目标点云 0.15 m 外的杂点。
-
max_iterations → 2000
说明:ICP 算子会在所有的初始评估值的基础上,分别进行不断的迭代优化,每一个初始评估值的最大优化迭代次数是 max_iterations 对应的数值。
-
transformation_epsilon → 0.00000001
说明:该值表示两次相邻迭代之间的平移变换矩阵的最大调整值。
-
rot_epsilon → 0.00000001
说明:该值表示两次相邻迭代之间的旋转变换矩阵的最大调整值。(通常transformation_epsilon与rot_epsilon的值一致。)
-
score_threshold → -1
说明:该值表示分数阈值,得分越低,匹配效果越好。如果最终的最优匹配结果得分超过该阈值,算子触发 failed 信号。默认值:-1,表示在计算结果中取最优值。
-
result_pose → 可视
-
-
设置 Transform 算子参数:
-
type → PointCloud
-
cloud → 可视 → 180
-
-
连接算子。
-
点击 RVS 运行按钮,点击面板上的
start
按钮,匹配开始。点击面板上iterate
按钮时,迭代离线数据中的目标点云进行模板匹配。
运行结果
如下图所示。在 3D 视图中最终显示原始色彩点云为目标点云,红色为匹配前模板点云,蓝色为匹配后点云。
至此您已经完成了本文档的所有内容,感谢您的耐心查阅,相信您一定对于 RVS 软件已有所了解,可以自主创造属于您的独特项目,若在使用中出现问题,请及时与我们反馈,发送邮件rvs-support@percipio.xyz!