DiSCO使用指南

"DiSCO Tutorial"

Posted by xxc on March 20, 2022

Basic Knowledge:

DiSCO:Differentiable Scan Context with Orientation是我去年在RAL上发表的一篇关于地点重识别的文章,它可以做到又快又好地识别室外场景中的回环,同时还能估计回环关键帧之间的相对旋转。我已经把DiSCO集成到一个大系统中,目前运行下来,表现非常令人满意。具体的介绍我之前的一篇blog有写,详见DiSCO 介绍

Motivation for this blog

最近有位同学在github上的repo给我提issue,我才发现上传到github的版本还有许多小bug没有及时修复。因此我以这篇教程文章为契机,顺便对开源的代码进行查漏补缺。开源代码在这里:DiSCO code

Dependencies

  • Ubuntu: 16.04-20.04
  • ROS: kinetic-noetic (optional,如果你需要接入ROS)
  • PyTorch: 1.4.0-1.6.0 (fft module is modified after 1.6.0)

这里PyTorch中的fft模块在1.6.0版本之后修改了接口,其实要改也很好改,就在models/DiSCO.py里面把torch.rfft()这个函数用新的替代掉就好了。

A Quick Use

w/o ROS

# 0. Clone the code from 
git clone https://github.com/MaverickPeter/DiSCO-pytorch
cd DiSCO-pytorch && mkdir log

# 1. Prepare python environment (e.g.:torch 1.4.0; python 3.7)
conda create -n disco_py37 python==3.7
conda activate disco_py37
pip install -r requirements.txt

# 2. Build point cloud processor
cd multi-layer-polar-cython/cython
python setup.py build_ext --inplace
mv gputransform.cpython-37m-x86_64-linux-gnu.so ../../

# 3. Download the pretrained model from https://drive.google.com/file/d/1yGFtNUavJT0kxS_mtYAE8U3FzOTpt3c4/view?usp=sharing and move the model.ckpt to the log/

# 4. Try inference.py
python inference.py

w/ ROS

# 0. Prepare workspace and clone the code from 
mkdir -p disco_ws/src && cd disco_ws/src
git clone https://github.com/MaverickPeter/DiSCO-pytorch
cd DiSCO-pytorch && mkdir log
mv dislam_msgs ../

# 1. Prepare python environment (e.g.:torch 1.4.0; python 3.7)
conda create -n disco_py37 python==3.7
conda activate disco_py37
pip install -r requirements.txt

# 2. Build point cloud processor
cd multi-layer-polar-cython/cython
python setup.py build_ext --inplace
mv gputransform.cpython-37m-x86_64-linux-gnu.so ../../

# 3. Download the pretrained model from https://drive.google.com/file/d/1yGFtNUavJT0kxS_mtYAE8U3FzOTpt3c4/view?usp=sharing and move the model.ckpt to the log/

# 4. catkin_make to generate DiSCO msg
cd disco_ws/
catkin_make

# 5. Try infer_ros.py
source devel/setup.bash
rosrun disco_ros infer_ros.py 

Train DiSCO from Scratch

1. Prepare data

# 1. Move the gputransform.cpython-37m-x86_64-linux-gnu.so to generating_queries/nclt/
# 2. Modify config.py
# 3. Prepare folder structure. For NCLT dataset, if you want to use our code for convenience you have to form the data into this file structure. **(occ_xm is an empty folder)**
├── 2012-02-04
│   ├── ground_truth
│   ├── occ_0.5m
│   └── velodyne_data
│       └── velodyne_sync
├── 2012-03-17
│   ├── ground_truth
│   ├── occ_3m
│   └── velodyne_data
│       └── velodyne_sync
...(you may need to download at least 4 rounds)

# 4. Generate pickle files
python generate_training_tuples_baseline_with_pose.py
python generate_test_sets.py

# 5. Train
cd ../../
python train_DiSCO.py

DiSCO w/o Network

class DiSCO(nn.Module):
    def __init__(self, output_dim):
        super(DiSCO, self).__init__()

        self.out_dim = output_dim
        self.col = int(np.sqrt(self.out_dim)/2)
        self.unet = UNet(cfg.num_height)
        self.device = torch.device("cuda:0")

    def forward_fft(self, input):
        median_output = torch.rfft(input, 2, normalized=True, onesided=False)
        median_output_r = median_output[:, :, :, :, 0]
        median_output_i = median_output[:, :, :, :, 1]
        output = torch.sqrt(median_output_r ** 2 + median_output_i ** 2 + 1e-15)
        output = fftshift2d(output)
        return output, median_output

    def forward(self, x):

        batchsize = x.size()[0]

        unet_out = self.unet(x) 
        # 如果你不想用network,直接把高度维加起来过fft也可以得到很好的效果。
        # unet_out = torch.sum(x, dim=1, keepdim=True)

        out, fft_result = self.forward_fft(unet_out)
        
        x = out.squeeze(1)
        x = x[:, (cfg.num_ring//2 - self.col):(cfg.num_ring//2 + self.col), (cfg.num_sector//2 - self.col):(cfg.num_sector//2 + self.col)]
        x = x.reshape(batchsize, -1)

        return x, out, fft_result, unet_out