Blensor是一款开源的点云仿真软件,是国外的研究人员在三维动画软件Blender基础上进行开发的,整个安装包很小,只有80M左右,能够模拟Lidar(Velodyne 32/64线等)、TOF相机、Kinect等,而且可以根据自己的需求调整传感器参数,也可以加入噪声模拟实际点云,总之是一款很优秀的点云仿真软件,但是目前国内对这款软件的介绍寥寥无几,几乎找不到相关的学习资料,所以在初步学习这款软件后,决定写一下简单的教程,帮助需要的伙伴快速入手(目前本人也在学习中,对其中的部分功能都还不熟悉,因此下面的教程只适用于对Blender软件零基础、只需快速上手拿到仿真点云数据的伙伴,欢迎大家一起交流)
一、软件下载
首先访问官网:https://www.blensor.org/ ,点击download下载即可(需要FQ),官网提供的有Windows、Linux、Mac三个版本的,Windows下的下载后解压直接打开即可,无需安装
安装好后打开是下面的界面
二、跑通官方demo
安装好以后,我们先尝试跑通官方demo,对这个点云的数据采集过程有个直观感受。
(1)官方demo下载(https://www.blensor.org/add_sensors.html)
(2)打开table_tutorial_color.blend文件,里面主要包含了两类:一台TOF相机和含有桌子杯子等的模型场景。
首先右键点击相机,保证相机处于使用状态中(相机实三角形为黄色,且出现坐标轴)
然后再点击single scan按钮进行点云数据采集。
至此,数据采集过程完成。上述只是简单的走了一遍流程,在实际应用过程中,需要用python编写脚本程序自动采集(不嫌麻烦的也可以手动采集),下面就以我个人的使用需求进行详细介绍。
三、实际使用
新建场景后,删除自带的模型和相机,导入自己的模型,Blensor支持包括.3ds、.ply、.obj、.stl等主流三维模型格式,导入后点击左下角的view/properties可以修改模型的尺寸、位置、姿态等,如下图所示。
然后加入相机,如下图。在右侧下方可以选择相机的类型,包括velodyne 32线、velodyne 64线、TOF、Kinect等,后面的参数也都可以直接进行调整以满足自己的需求。
在调整好所有参数之后,下面介绍如何用python进行数据收集。(其实上述基本所有的操作都可以用python实现,比如卫星模型比例、位置这些,看个人习惯了)
点击左下角按钮,会出现很多功能,这里我们介绍两个,Text Editor和Python Console
(1)Text Editor主要是用来编写脚本程序,当然目前支持的也就是Python,里面可以设置显示行数和代码高亮等,虽然比不上VS Code、PyCharm等编辑器好用,但是也算很良心了,毕竟几十兆的软件……另外提醒一下,这个是Python3.0的语法。一般我们的程序就是写在这里,写完后点击“Run Script”就能运行了,这里不支持断点调试,同时因为会用到Blensor自己的库函数,所以外用编辑器也不太行,这个是个硬伤,但是好在这个软件有个控制台,简单的语法错误导致编译失败的可以用这个解决,如果是内在逻辑错误,就慢慢检查代码吧,good luck……(这个自带的系统控制台叫“Toggle System Console”,在界面左上方“Window”下拉菜单里面)
(2)Python Console其实很多人应该不陌生,就是个最基本的程序控制台,通过该控制台能输入一些基本的指令看到相关属性数据啥的。具体可以在“Outliner”和“Properties”中查看,包括点云数据、类型等。
重点:Blensor中所有的指令数据都给了非常具体的函数接口,这一点是我个人觉得最赞的,省去了大量阅读开发文档的时间,每个想要调用的数据或者按钮,直接鼠标放在相应的位置即可。
另外关于数据导出的问题:
Blensor官方说法是可以提供pcd的点云格式数据,但是!这个格式不知道为啥,完全不对,数据帧头和数据包是两个文件,而且数据包的文件有问题,没法直接读取,可能是我个人的理解偏差,总之官方给的数据我没法用。
没有pcd格式点云数据就得自己想办法,好在官方还有原始数据可供读取,因此可以采用一帧一帧的数据访问,然后保存下来使用。
具体方法:在每一次扫描后,清除上一帧的扫描结果(不然直接读取数据会包含之前的,导致出错),通过这个函数进行数据访问:bpy.data.meshes[“ ”].vertices.co[]
此外,关于清除上一帧的点云数据问题,在Single scan按钮后面,有一个Delete scans,这个按钮只是清除3D 视图中的扫描痕迹,完全不会清除扫描数据,因此我们需要用bpy.data.objects.remove()函数,这样清除后的数据再进行扫描,就能拿到当前帧下的扫描结果。
下面附一下我自己的代码,可以帮助大家进一步理解
(其中999 999 999仅仅是我自己定义的数据分割标志,方便后续处理,相应的场景文件已传至百度云:https://pan.baidu.com/s/1xkYxF42yUfw_4T_QJJnUOQ 提取码:h4ir)
import bpy import math from numpy import arange from bpy import data as D from bpy import context as C from mathutils import * from math import * import blensor """set the parameters of tof """ scanner = bpy.data.objects["Camera"]; scanner.location = (0,-6,0); scanner.rotation_euler= (90/180*pi,0,0/180*pi); scanner.scan_type = "tof"; """clear all scanning datas """ for item in bpy.data.objects: if item.type == \'MESH\' and item.name.startswith(\'Scan\'): bpy.data.objects.remove(item) """set the position and attitude of satellite""" satellite=bpy.data.objects["Satellite"]; satellite.rotation_euler=(0,0,0); satellite.location=(0,0,0); """clear the scanning in view windows and start newly scan""" bpy.ops.blensor.delete_scans(); bpy.ops.blensor.scan(); f=open("C:/Users/Justice/Desktop/TOF spacecraft position&attitude estimation by Blensor/data.txt","w") for z_angle in arange(0,360,5): #clear all scanning datas for item in bpy.data.objects: if item.type == \'MESH\' and item.name.startswith(\'Scan\'): bpy.data.objects.remove(item) satellite.rotation_euler=(20,0,z_angle/180*pi); bpy.ops.blensor.delete_scans(); bpy.ops.blensor.scan(); for item in bpy.data.objects: if item.type == \'MESH\' and item.name.startswith(\'Scan\'): #s_angle="data%" %(z_angle/2+1)) f.write("999\t999\t999\n") for sp in item.data.vertices: #print(\'X=%+#5.3f\tY=%+#5.3f\tZ=%+#5.3f\' % (sp.co[0], sp.co[1],sp.co[2])); str=\'%#5.3f\t%#5.3f\t%#5.3f \n\' % (sp.co[0], sp.co[1],sp.co[2]); f.write(str);