故跬步不休,跛鱉千里;累積不輟,可成丘阜,——(西漢)劉安《淮南子·說林訓》
差不多從夏天的時候開始就一直在找有沒有什么方法可以生成ROS bag資料,當時只找到了錄制的方法,使用圖片等原始資料生成的方法一直沒找到,直到最近看到一篇博客使用了一個Python腳本將ASL資料轉換成了ROS bag,試了一下挺好用的,欣喜若狂,有了它就可以將自己的資料按照ASL格式進行組織,之后使用腳本直接生成ROS bag就可以了,
簡單說一下使用方法,因為需要用到ROS的一些Python包,所以使用的Python環境必須是安裝了ROS的,我是在Ubuntu 16.04 LTS下運行的,安裝的ROS Kinetic,運行環境其實和這篇博客的一樣:一周小結(七)——從零開始配置VINS-Mono運行環境,不知道什么原因,在Pycharm中匯入相關包時一直報錯,但是相同的Python版本在終端卻可以,大家如果有知道什么原因的歡迎評論區留言,所以無奈就拋棄了IDE而在終端運行,使用時需要給出ASL資料解壓的檔案路徑以及生成的ROS bag資料的路徑、名稱,后者可以使用默認值(home檔案夾下生成output.bag),例如:
python '/home/dong/Code/zip2bag/zip2bag.py' --folder /home/dong/catkin_ws/dataset/1
最后給出Python腳本,大家也可以根據自己資料的組織結構、命名規則等進行適當修改,
#!/usr/bin/env python
print
"importing libraries"
import rosbag
import rospy
from sensor_msgs.msg import Image
from sensor_msgs.msg import Imu
from geometry_msgs.msg import PointStamped
# import ImageFile
# import PIL.ImageFile as ImageFile
import time, sys, os
import argparse
import cv2
import numpy as np
import csv
# structure
# dataset/cam0/data/TIMESTAMP.png
# dataset/camN/data/TIMESTAMP.png
# dataset/imu0/data.csv
# dataset/imuN/data.csv
# dataset/leica0/data.csv
# setup the argument list
parser = argparse.ArgumentParser(description='Create a ROS bag using the images and imu data.')
parser.add_argument('--folder', metavar='folder', nargs='?', help='Data folder')
parser.add_argument('--output_bag', metavar='output_bag', default="output.bag", help='ROS bag file %(default)s')
# print help if no argument is specified
if len(sys.argv) < 2:
parser.print_help()
sys.exit(0)
# parse the args
parsed = parser.parse_args()
def getImageFilesFromDir(dir):
'''Generates a list of files from the directory'''
image_files = list()
timestamps = list()
if os.path.exists(dir):
for path, names, files in os.walk(dir):
for f in files:
if os.path.splitext(f)[1] in ['.bmp', '.png', '.jpg']:
image_files.append(os.path.join(path, f))
timestamps.append(os.path.splitext(f)[0])
# sort by timestamp
sort_list = sorted(zip(timestamps, image_files))
image_files = [file[1] for file in sort_list]
return image_files
def getCamFoldersFromDir(dir):
'''Generates a list of all folders that start with cam e.g. cam0'''
cam_folders = list()
if os.path.exists(dir):
for path, folders, files in os.walk(dir):
for folder in folders:
if folder[0:3] == "cam":
cam_folders.append(folder)
return cam_folders
def getImuFoldersFromDir(dir):
'''Generates a list of all folders that start with imu e.g. cam0'''
imu_folders = list()
if os.path.exists(dir):
for path, folders, files in os.walk(dir):
for folder in folders:
if folder[0:3] == "imu":
imu_folders.append(folder)
return imu_folders
def getImuCsvFiles(dir):
'''Generates a list of all csv files that start with imu'''
imu_files = list()
if os.path.exists(dir):
for path, folders, files in os.walk(dir):
for file in files:
if file[0:3] == 'imu' and os.path.splitext(file)[1] == ".csv":
imu_files.append(os.path.join(path, file))
return imu_files
def loadImageToRosMsg(filename):
image_np = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
timestamp_nsecs = os.path.splitext(os.path.basename(filename))[0]
timestamp = rospy.Time(secs=int(timestamp_nsecs[0:-9]), nsecs=int(timestamp_nsecs[-9:]))
rosimage = Image()
rosimage.header.stamp = timestamp
rosimage.height = image_np.shape[0]
rosimage.width = image_np.shape[1]
rosimage.step = rosimage.width # only with mono8! (step = width * byteperpixel * numChannels)
rosimage.encoding = "mono8"
rosimage.data = image_np.tostring()
return rosimage, timestamp
def createImuMessge(timestamp_int, omega, alpha):
timestamp_nsecs = str(timestamp_int)
timestamp = rospy.Time(int(timestamp_nsecs[0:-9]), int(timestamp_nsecs[-9:]))
rosimu = Imu()
rosimu.header.stamp = timestamp
rosimu.angular_velocity.x = float(omega[0])
rosimu.angular_velocity.y = float(omega[1])
rosimu.angular_velocity.z = float(omega[2])
rosimu.linear_acceleration.x = float(alpha[0])
rosimu.linear_acceleration.y = float(alpha[1])
rosimu.linear_acceleration.z = float(alpha[2])
return rosimu, timestamp
# create the bag
bag = rosbag.Bag(parsed.output_bag, 'w')
# write images
camfolders = getCamFoldersFromDir(parsed.folder)
for camfolder in camfolders:
camdir = parsed.folder + "/{0}".format(camfolder) + "/data"
image_files = getImageFilesFromDir(camdir)
for image_filename in image_files:
image_msg, timestamp = loadImageToRosMsg(image_filename)
bag.write("/{0}/image_raw".format(camfolder), image_msg, timestamp)
# write imu data
imufolders = getImuFoldersFromDir(parsed.folder)
for imufolder in imufolders:
imufile = parsed.folder + "/" + imufolder + "/data.csv"
topic = os.path.splitext(os.path.basename(imufolder))[0]
with open(imufile, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
headers = next(reader, None)
for row in reader:
imumsg, timestamp = createImuMessge(row[0], row[1:4], row[4:7])
bag.write("/{0}".format(topic), imumsg, timestamp)
# write leica data
leicafile = parsed.folder + "/leica0/data.csv"
with open(leicafile, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
headers = next(reader, None)
for row in reader:
timestamp_nsecs = str(row[0])
timestamp = rospy.Time( int(timestamp_nsecs[0:-9]), int(timestamp_nsecs[-9:]) )
pos = PointStamped()
pos.header.stamp = timestamp
pos.point.x = float(row[1])
pos.point.y = float(row[2])
pos.point.z = float(row[3])
bag.write("/leica/position", pos, timestamp)
bag.close()
又到年底了,一年快要結束了,去年因為出差的原因(其實就是因為懶),沒有寫年終總結與新年展望,今年可不能這樣了,先給自己立一個小小的flag,O(∩_∩)O哈哈~,年底見!
參考:
1、The EuRoC MAV Dataset
2、從 EuRoC MAV Dataset 的 .zip 檔案生成 .bag 的 python 腳本
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/230732.html
標籤:python
