用CubeSLAM跑自己的数据集

针对CubeSLAM本博客内容如下,主要是阅读论文和代码的一些结果总结,还有一部分总结未完成,同样使用或者对语义slam感兴趣有经验的欢迎交流,该博客后面也会不段更新cubeslam在自己的数据集上的使用结果和一些避坑指南:
 1. cubeSLAM主要贡献
 2. 2D->3D的cube转换
 3. 使用自己的数据集
 
1. 主要贡献:
这篇文章在语义SLAM中好评较多,主要是与常见的ORBSLAM实现来物体级别的结合;
主要分为两部分,第一部分为2d部分,主要是可以通过平面的bbox生成出立体的cube,生成出得box带有9个参数,分别是三维的位置信息(tx,ty,tz),三维的角度信息,以及三维的尺寸信息(dx,dy,dz); 第二个贡献就是将3维cube与ORBSLAM的结合,将cube的位姿信息也添加到了相机位姿的优化中,因此,最终的BA方程将包括三个优化项,分别是:相机和物体之间,相机位姿和地图点,以及物体位姿与地图点之间的误差,而原ORBSLAM中只包含有第二项,及地图点在相机位姿下的重投影误差;

2. 2D->3D的cube转换
个人觉得这一部分很重要的原因是因为目前3d的物体检测相对于2d的物体检测来讲,准确度还是有待提高,尤其在SLAM中使用3d点云进行物体检测 与 单纯地使用2d图像进行检测所需要的软件和硬件都有差别,这次测试即为使用2d的boundingbox,传入到orb_object_slam中进行;
首先说一下检测大致的思路:输入为2维的bbox,文件使用格式为(left_up_point_x, left_up_point_y,width,height)的格式, 输出为3d的cube,也就是上面所说的9个参数,cubeobject的位姿+cube的维度;
具体过程:
a. cube的坐标系建立为每一个cube的中心,坐标的各个方向为向右为x,向前为y,向上为z,符合右手坐标系,但是与IMU坐标系相对来讲有一个90度的旋转;这点很重要,因为如果需要运行自己的数据机,就要知道最开始相机位姿与地面之间的关系,也就是后面会提到的Init_to_Ground: 有兴趣的可以直接参考我在git上提出的问题,有作者本人的回答:https://github.com/shichaoy/cube_slam/issues/32
b. 这篇文章使用来vanishing point来恢复cube的三维及信息;
第一步,vanishing point的定义
我个人的理解,这些点通俗来讲就是物体投影到平面图像之后的各个边的交叉点;(按理说,一个空间中存在的立方体的两个长,两个宽边和两个高边都是彼此平行的,但是投影到平面之后,发生仿射变换,不再保平行,所以,这些边的延长线将会相交到一起);
关于VP的定义具体可以参考《多视图几何》中的定义,而论文中直接采用来VP的计算为 VPi = KRcol(i); 也就是第i个VP的计算是其相对于相机的旋转矩阵的第i列以及相机的内参K决定的;
第二步,确定VPs后即可通过VPs来计算二维的角点,也就是立方体的各个角点的二维坐标,通过VPs和bbox的交点计算;
第三步,计算3Dbox,也就是当前cube的pose,这里有一个很重要的投影公式,即

该公式即为立方体的各个角点从object坐标系到camera坐标系的再到图像坐标系的一个投影,最终的重投影误差也是由这个公式计算;
这里举个例子,如果按照右侧为x正方向,前侧为y正方向,上方为z正方向,则object坐标系的原点位于该cube的中心,那么右前方上面的角点坐标即为(dx,dy,dz),其他点同理,这是在object coordinate下的坐标,经过旋转矩阵R和平移t即可转移到相机坐标系下,再经过投影公式pai即转换至这些角点再图像中的二维坐标;

第四步:定义cost function:
接下来说到如何去计算该object cube的参数O={R,t,d}; 这里列出cost function如下:

该代价函数主要由三部分组成:距离代价函数,角度代价函数,和形状约束;其中距离代价函数指的是上图中蓝色实线上的点到bbox对角线(也就是右3的那条黑线)之间的距离;角度代价函数即指上图left图像的较长线段与vp角度之间的关系;形状约束主要是指对长宽比过大的cube的惩罚;

这一部分的代码主要集中在detect_3d_cuboid部分,感兴趣的可以对detect_cuboid()函数进一步研究;

3. OBJECT SLAM
这里主要说一下静态物体的objectslam,动态的部分我还没有整理,有整理过的伙伴欢迎交流;SLAM部分主要分为两块,一是代价函数的介绍,二是代价函数详解;
第一部分:代价函数;
原本的ORBSLAM的代价函数为最小化地图点的重投影误差;而添加了物体之后的slam,其代价函数也对应地增加;具体如下:

其中第1和第3个为新增的误差部分;
第一部分物体在相机中的重投影误差;
这一部分可以分为两种情况:一种是使用rgbd相机时,object的位置信息比较精确,这时可以在精确值和测量值之间计算一个误差;二是只有图像信息,比如单目SLAM的情况;可以将object cube的各个顶点的坐标,由object frame 到camera frame经R,t 进行转换,再将相机坐标系下的顶点,经过相机的投影矩阵,即可得到对应的其在图像上的坐标,该坐标与实际的图像坐标之间的误差,即obejct的重投影误差,因此可以作为一个优化项;

第二部分为传统是地图点重投影误差,不再赘述;

第三部分是地图点与object cube之间存在的约束;
基于如下的原理:如果一个点在图像中的坐标位于bbox内部,那么该点也就存在与object cube的内部;一般情况下,orbslam保存的地图点都是在世界坐标系下,将这些地图点由世界坐标系转换至相机坐标系中,再转换至object坐标系中,那么该点在obejct坐标系中的坐标应该是小于各个方向的dimension;因此,这部分也可以构成一个约束项;

在自己的数据集上运行CubeSLAM:

运行之前:

1. 首先说一下cubeslam代码分几个模块,具体每个模块的作用我在刚开始的时候也是比较迷茫地,所以理解起整个项目会比较慢,具体如下:

2. 下面列举一些需要的参数, 可以在对应的launch文件中进行修改,也可以自己在ros_mono.cc中按照自己的需求改动:

1. 先单独运行边缘检测的部分,进行edge_detection, 可以运行单张图片,也可以写一个跑rosbag的,直接将包中的图像全部转换;

 2. filter_2d_obj_txts中存放通过yolo或者其他方法检测出的boundingbox, 文件名和文件格式如下:

 

这里面四个数字分别是boundingbox的左上角坐标x,y 以及boundingbox的宽和高;

当然,这些都可以在代码中灵活修改,具体对应的代码是orb_object_slam中的Tracking.cc中(可以通过搜索filter_2d_obj_txts)

3.  raw_imgs 中存放原图, 这里图片的名称需要和代码中的一致,不太建议修改代码,因为类似的访问太多,比较耗费精力

4. 运行orb_object_slam:

    ./devel/lib/orb_object_slam/ros_mono path_to_vocabulary/Vocabulary/ORBvoc.bin path_to_camera_matrix/Examples/Monocular/Example.yaml start_id

这里的测试中使用的是单目slam,一些参数具体的意义会在后面以表格的形式更新,这里的start_id也是为了方便测试在后期添加的;
在自己的数据集上跑的时候要注意Tracking.cpp中InitToGround的修改,具体参考https://github.com/shichaoy/cube_slam/issues/32;该参数决定来物体的scale,算是间接决定,当参数设置过大时会出现很大的cube,如图:

上图中图像的位置基本正确,只是size很大,同时也会导致整个slam的size出现差别;
 

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
stm32cube是一个软件平台,用于开发和编程STM32微控制器。要实现串口接收数据,首先需要初始化串口配置。在stm32cube中,可以使用HAL库函数进行串口初始化。为了接收数据,需要配置串口的波特率、数据位、停止位以及校验位等参数。此外,还需要使能串口的接收功能。 接下来,可以在主函数中创建一个缓冲区数组,用于存储接收到的数据。然后,可以使用HAL库函数中提供的接收函数,比如HAL_UART_Receive(),将接收到的数据存储到缓冲区数组中。这些函数通常包含在stm32cube的HAL_UART库中。 可以使用while循环不断接收数据,可以通过判断接收到的数据长度是否等于期望的数据长度来判断是否接收到了完整的数据。如果接收到完整的数据,则可以对数据进行处理或者进行其他操作。如果没有接收到完整的数据,则继续等待。可以根据需求设置超时时间,当超时时间到达后,还没有接收到完整的数据,可以进行错误处理或者重试。 在处理完数据后,可以根据需要清空缓冲区数组,以便下一次接收数据的使用。 需要注意的是,使用stm32cube进行串口接收数据之前,需要先配置GPIO引脚作为串口的接收引脚,并将其与特定的串口外设进行绑定。 总的来说,stm32cube实现串口接收数据主要包括初始化串口配置、创建接收缓冲区数组、设置超时时间、接收数据并进行处理等步骤。使用STM32Cube的HAL库函数可以方便地实现这些功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值