基于openpcdet的Pointpillars之ROS可视化
一、实验环境
Ubuntu 18.04
cmake version 3.13.1
cuda 10.2
python 3.7
pytorch 1.8.1
二、准备条件
(1)安装好ROS
(2)搭建好OpenPCDet,确保其运行成功,尤其是虚拟环境没有问题。参考OpenPCDet安装及其3D检测算法实现
(3)代码获取:具体做法就是,在github上下载下来原作者的源码,然后将复现好的OpenPCDet的部分文件进行迁移到下载好的github的对应文件夹中,修改源码,进行编译。
(4)下载kitti的原始数据集,并将其转化为.bag格式,具体办法,可以参考下面:
将kitti数据集中的velodyne points转换为ROS bag文件
三、下载源码,确定文件架构
mkdir -p ~/ws/pointpillars_ros/src
cd pointpillars_ros/src
git clone https://github.com/BIT-DYN/pointpillars_ros
我的文件架构:
四、将Openpcdet的部分文件迁移至对应文件
将Openpcdet工程中的OpenPCDet/tools中的全部文件以及/OpenPCDet/pcdet(尤其注意不要遗漏pcdet文件),
复制粘贴放入到src/pointpillars/tools文件夹下(然后放入数据检查一下openpcdet移植过来还能跑通不):
五、具体代码修改与讲解
5.1 先修改ros.py代码
5.1.1 三个路径的修改
# 下边的路径改成自己的
sys.path.append("/home/dyn/project_test/pointpillars_ros/src/pointpillars_ros")
# 54行后边
config_path = rospy.get_param("/config_path", "/home/dyn/project_test/pointpillars_ros/src/pointpillars_ros/tools/cfgs/kitti_models/pointpillar.yaml")
ckpt_path = rospy.get_param("/ckpt_path", "/home/dyn/project_test/pointpillars_ros/src/pointpillars_ros/tools/models/pointpillar_7728.pth")
5.1.2 修改旋转参数
大概在ros.py的86行前后。因为开源作者安装的雷达有偏角,所以这里置0就行。
# 旋转轴
#rand_axis = [0,1,0]
#旋转角度
#yaw = 0.1047
#yaw = 0.0
#返回旋转矩阵
#rot_matrix = self.rotate_mat(rand_axis, yaw)
#np_p_rot = np.dot(rot_matrix, np_p[:,:3].T).T
# convert to xyzi point cloud
x = np_p[:, 0].reshape(-1)
y = np_p[:, 1].reshape(-1)
z = np_p[:, 2].reshape(-1)
if np_p.shape[1] == 4: # if intensity field exists
i = np_p[:, 3].reshape(-1)
else:
i = np.zeros((np_p.shape[0], 1)).reshape(-1)
points = np.stack((x, y, z, i)).T
5.1.3 修改ros.py代码的大概110行前后(去除掉不合适的检测框,我设置的阈值为0.5)
# 组装数组字典
input_dict = {
'points': points,
'frame_id': msg.header.frame_id,
}
data_dict = self.demo_dataset.prepare_data(data_dict=input_dict) # 数据预处理
data_dict = self.demo_dataset.collate_batch([data_dict])
load_data_to_gpu(data_dict) # 将数据放到GPU上
pred_dicts, _ = self.model.forward(data_dict) # 模型前向传播
scores = pred_dicts[0]['pred_scores'].detach().cpu().numpy()
mask = scores > 0.5
scores = scores[mask]
boxes_lidar = pred_dicts[0]['pred_boxes'][mask].detach().cpu().numpy()
label = pred_dicts[0]['pred_labels'][mask].detach().cpu().numpy()
num_detections = boxes_lidar.shape[0]
#rospy.loginfo("The num is: %d ", num_detections)
# print(boxes_lidar)
# print(scores)
# print(label)
如何想用GPU加载训练模型的话,将ros.py:
self.model.load_params_from_file(filename=ckpt_path, logger=logger, to_cpu=True)
改为:
self.model.load_params_from_file(filename=ckpt_path, logger=logger, to_cpu=False)
5.1.4 整体
但是修改后,原作者的代码当时一直没有跑通,可能部分代码框架思路不一样。如果是kitti数据集,可以直接复制下面的:
#!/usr/bin/env python3
import rospy
from sensor_msgs.msg import PointCloud2,PointField
import sensor_msgs.point_cloud2 as pc2
from std_msgs.msg import Header
from jsk_recognition_msgs.msg import BoundingBox, BoundingBoxArray
import time
import numpy as np
from pyquaternion import Quaternion
import argparse
import glob
from pathlib import Path
import numpy as np
import torch
import scipy.linalg as linalg
import sys
sys.path.append("/home/ypx/ws/pointpillars_ros/src/pointpillars_ros")
from pcdet.config import cfg, cfg_