欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASL数据转换为ROS bag数据

程序员文章站 2022-08-29 14:54:41
故跬步不休,跛鳖千里;累积不辍,可成丘阜。——(西汉)刘安《淮南子·说林训》差不多从夏天的时候开始就一直在找有没有什么方法可以生成ROS bag数据,当时只找到了录制的方法,使用图片等原始数据生成的方法一直没找到。直到最近看到一篇博客使用了一个Python脚本将ASL数据转换成了ROS bag,试了一下挺好用的,欣喜若狂。有了它就可以将自己的数据按照ASL格式进行组织,之后使用脚本直接生成ROS bag就可以了。简单说一下使用方法。因为需要用到ROS的一些Python包,所以使用的Python环境必...

故跬步不休,跛鳖千里;累积不辍,可成丘阜。——(西汉)刘安《淮南子·说林训》

差不多从夏天的时候开始就一直在找有没有什么方法可以生成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://blog.csdn.net/weixin_38141453/article/details/110679751