1. 程式人生 > >Karto_slam跑鐳射雷達(北陽ust-10lx下一篇介紹使用)

Karto_slam跑鐳射雷達(北陽ust-10lx下一篇介紹使用)

0.當前配置

  • Ubuntu 16.04
  • ROS Kinetic
  • Opencv 3.4.1
  • Ceres-solver
  • gcc version 5.4.0 20160609 (g++)
  • *Eigen3
  • *G2O

1.前言

本人當下在學習slam_karto,在網上搜尋相關的部落格,發現大家使用karto的並不多,大多都是在介紹hector_slam和gmapping_slam.當然還有Google的cartographer.參考他人的部落格,gmapping與karto效果比較相似,但似乎gmapping的計算更加複雜,已經整合到ros中,使用的也比較多,cartographer效果很好,缺點是cpu佔用率和記憶體開銷較大,程式碼也非常高深(目前我感覺不太容易看懂,畢竟c++有點陌生還…).所以準備學習下karto,順便可能的話,也分享下自己的經驗.

2.安裝Karto

因為slam_karto是依賴於open_karto的,所以要先安裝open_karto.有兩種方式安裝karto_slam,我本人比較推薦使用第二種方式,雖然略微複雜一點,但是後續學習修改原始碼會方便一點.

第一種:

sudo apt-get install ros-kinetic-open-karto
sudo apt-get install ros-kinetic-slam-karto

注意kinetic為你ros對應的版本.
第二種:

cd catkin_ws/src
git clone https://github.com/ros-perception/open_karto.git
git clone https://github.com/ros-perception/slam_karto.git cd .. catkin_make

catkin_make沒有報錯的話,基本上就安裝成功了.你可以嘗試執行,但在執行之前別忘記執行下source devel/setup.bash也可以一勞永逸,在home下的.bashrc末尾追加

source /home/yourusername/catkin_ws/devel/setup.bash

分兩個Terminal執行:

roscore
rosrun slam_karto slam_karto

現在沒有資料,肯定沒有輸出了,如果報錯的話可能電腦壞來吧,要報錯也是你catkin_make

報錯把.(由於我修改來launch檔案,本來可以roslaunch slam_karto karto_slam.launch啟動的….再這麼寫怕和我有區別).

3.下載資料集

之前大家的教程也是,光寫文字或者執行,就是不給資料集,搞得我光找資料集就找了半天,功夫不負有心人還真讓我給找到了,還不少呢.
戳這裡:
SKrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
我不確定這個需不需要翻牆,因為我們學校的網沒有牆似乎…
下載說明:

  1. 進去網站後點你想下載的對應的”download log file”
  2. 然後你可能會看到變成頁面一堆資料
  3. ctrl+a
  4. ctrl+c(你懂的,全部複製,這就是你要的資料集)
  5. 新建一個文件如data.clf,存之.注意是.clf.

4.處理資料集

這個.clf不是我們用的,我們需要把它轉化為特定格式的.bag檔案,然後rosbag play來使用資料集,
下面給出轉化用的python程式碼.
先說使用方法:

  1. 在你slam_karto下建立一個script資料夾,與launch資料夾同級目錄.
  2. 把下面程式碼建立成一個.py檔案如convert.py,然後放到script中.
  3. 因為他要用到ros庫所以必須儲存到某個parkagescript中.
  4. cd這個script下,然後python convert.py path/data.clf path/data.bag 轉化成功.

這個程式碼是python2.7,python3.5+的自己修改下不相容的語法即可.程式碼參考這位博主.還有一位,暫時找不到來,往後補上.

#!/usr/bin/env python
#coding=utf8


'''This is a converter for the Intel Research Lab SLAM dataset
   ( http://kaspar.informatik.uni-freiburg.de/~slamEvaluation/datasets/intel.clf )
   to rosbag'''

import rospy
import rosbag
from sensor_msgs.msg import LaserScan
from nav_msgs.msg import Odometry
from math import pi
from tf2_msgs.msg import TFMessage
from geometry_msgs.msg import TransformStamped
import tf
import sys

def make_tf_msg(x, y, theta, t,base,base0):
    trans = TransformStamped()
    trans.header.stamp = t
    trans.header.frame_id = base
    trans.child_frame_id = base0
    trans.transform.translation.x = x
    trans.transform.translation.y = y
    q = tf.transformations.quaternion_from_euler(0, 0, theta)
    trans.transform.rotation.x = q[0]
    trans.transform.rotation.y = q[1]
    trans.transform.rotation.z = q[2]
    trans.transform.rotation.w = q[3]

    msg = TFMessage()
    msg.transforms.append(trans)
    return msg
if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "請輸入dataset檔名。" 
        exit()
    print "正在處理" + sys.argv[1] + "..."
    with open(sys.argv[1]) as dataset:
        with rosbag.Bag(sys.argv[2], 'w') as bag:
            i = 1
            for line in dataset.readlines():
                line = line.strip()
                tokens = line.split(' ')
                if len(tokens) <= 2:
                    continue
                if tokens[0] == 'FLASER':
                    msg = LaserScan()
                    num_scans = int(tokens[1])

                    if num_scans != 180 or len(tokens) < num_scans + 9:
                        rospy.logwarn("unsupported scan format")
                        continue

                    msg.header.frame_id = 'base_laser_link'
                    t = rospy.Time(float(tokens[(num_scans + 8)]))
                    msg.header.stamp = t
                    msg.header.seq = i
                    i += 1
                    msg.angle_min = -90.0 / 180.0 * pi
                    msg.angle_max = 90.0 / 180.0 * pi
                    msg.angle_increment = pi / num_scans
                    msg.time_increment = 0.2 / 360.0
                    msg.scan_time = 0.2
                    msg.range_min = 0.001
                    msg.range_max = 50.0
                    msg.ranges = [float(r) for r in tokens[2:(num_scans + 2)]]
                    msg.ranges.append(float(0))  #我修改了這

                    bag.write('scan', msg, t)

                    odom_x, odom_y, odom_theta = [float(r) for r in tokens[(num_scans + 2):(num_scans + 5)]]
                    tf_msg = make_tf_msg(odom_x, odom_y, odom_theta, t,'odom','base_link')
                    bag.write('tf', tf_msg, t)

                elif tokens[0] == 'ODOM':
                    odom_x, odom_y, odom_theta = [float(t) for t in tokens[1:4]]
                    t = rospy.Time(float(tokens[7]))
                    tf_msg = make_tf_msg(0, 0, 0, t,'base_link','base_laser_link')
                    bag.write('tf', tf_msg, t)

5.盡情跑吧

roscore
rosrun slam_karto slam_karto
rosbag play data.bag

如果你裝來Rviz的話,可以在Rviz中看出效果了,沒裝這裡也不介紹怎麼裝了,哈哈.

rosrun rviz rviz

效果圖:
這裡寫圖片描述

6.可能出錯的地方

應該沒有了吧,catkin_make可能容易出錯,因為那是我根據印象寫下的步驟.其次就是python2.7的.
注意那個python程式碼我改了一點,是因為slam_karto預設的雷達資料應該是180度,以及181條鐳射束,而下載的資料集是180個鐳射束,所以我最後增加了一條深度為0的鐳射束.
有問題留言討論吧,看到會及時回你.

溜溜球.skr!