Skip to content

Instantly share code, notes, and snippets.

@marc-hanheide
Last active August 22, 2023 09:31
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save marc-hanheide/4c35796e6a7cd0042dca274bf9e5e9f5 to your computer and use it in GitHub Desktop.
Save marc-hanheide/4c35796e6a7cd0042dca274bf9e5e9f5 to your computer and use it in GitHub Desktop.
convert ROS bag to cvs files
'''
This script saves each topic in a bagfile as a csv.
Accepts a filename as an optional argument. Operates on all bagfiles in current directory if no argument provided
Usage1 (for one bag file):
python bag2csv.py filename.bag
Usage 2 (for all bag files in current directory):
python bag2csv.py
Written by Nick Speal in May 2013 at McGill University's Aerospace Mechatronics Laboratory. Bugfixed by Marc Hanheide June 2016.
www.speal.ca
Supervised by Professor Inna Sharf, Professor Meyer Nahon
'''
import rosbag, sys, csv
import time
import string
import os #for file management make directory
import shutil #for file management, copy file
#verify correct input arguments: 1 or 2
if (len(sys.argv) > 2):
print "invalid number of arguments: " + str(len(sys.argv))
print "should be 2: 'bag2csv.py' and 'bagName'"
print "or just 1 : 'bag2csv.py'"
sys.exit(1)
elif (len(sys.argv) == 2):
listOfBagFiles = [sys.argv[1]]
numberOfFiles = 1
print "reading only 1 bagfile: " + str(listOfBagFiles[0])
elif (len(sys.argv) == 1):
listOfBagFiles = [f for f in os.listdir(".") if f[-4:] == ".bag"] #get list of only bag files in current dir.
numberOfFiles = str(len(listOfBagFiles))
print "reading all " + numberOfFiles + " bagfiles in current directory: \n"
for f in listOfBagFiles:
print f
print "\n press ctrl+c in the next 10 seconds to cancel \n"
time.sleep(10)
else:
print "bad argument(s): " + str(sys.argv) #shouldnt really come up
sys.exit(1)
count = 0
for bagFile in listOfBagFiles:
count += 1
print "reading file " + str(count) + " of " + str(numberOfFiles) + ": " + bagFile
#access bag
bag = rosbag.Bag(bagFile)
bagContents = bag.read_messages()
bagName = bag.filename
#create a new directory
folder = string.rstrip(bagName, ".bag")
try: #else already exists
os.makedirs(folder)
except:
pass
shutil.copyfile(bagName, folder + '/' + bagName)
#get list of topics from the bag
listOfTopics = []
for topic, msg, t in bagContents:
if topic not in listOfTopics:
listOfTopics.append(topic)
for topicName in listOfTopics:
#Create a new CSV file for each topic
filename = folder + '/' + string.replace(topicName, '/', '_slash_') + '.csv'
with open(filename, 'w+') as csvfile:
filewriter = csv.writer(csvfile, delimiter = ',')
firstIteration = True #allows header row
for subtopic, msg, t in bag.read_messages(topicName): # for each instant in time that has data for topicName
#parse data from this instant, which is of the form of multiple lines of "Name: value\n"
# - put it in the form of a list of 2-element lists
msgString = str(msg)
msgList = string.split(msgString, '\n')
instantaneousListOfData = []
for nameValuePair in msgList:
splitPair = string.split(nameValuePair, ':')
for i in range(len(splitPair)): #should be 0 to 1
splitPair[i] = string.strip(splitPair[i])
instantaneousListOfData.append(splitPair)
#write the first row from the first element of each pair
if firstIteration: # header
headers = ["rosbagTimestamp"] #first column header
for pair in instantaneousListOfData:
headers.append(pair[0])
filewriter.writerow(headers)
firstIteration = False
# write the value from each pair to the file
values = [str(t)] #first column will have rosbag timestamp
for pair in instantaneousListOfData:
if len(pair)>1:
values.append(pair[1])
filewriter.writerow(values)
bag.close()
print "Done reading all " + str(numberOfFiles) + " bag files."
@kamathhrishi
Copy link

How do you install the rosbag module?

@dakejahl
Copy link

dakejahl commented Jul 9, 2019

Thanks for this!!

@tomisilander
Copy link

Thanks,
I suggest making the line 85 to be

splitPair = string.split(nameValuePair, ':', 1)

(I had ':' in value so it did not work).

@al-aminrahman
Copy link

Where is the output .CSV file will be located?

@Shivani1796
Copy link

Hello, I have around 1800 images but its giving only 32 .csv file why so ? Also the pose files are not correct any other method by which we could get pose data (converting .bag --> .csv )

@marc-hanheide
Copy link
Author

marc-hanheide commented Dec 28, 2019

I have just taken this gist from the original source and made it work in 2016 for my own purposes. I'm afraid, I don't maintain it, but I welcome anyone taking it and hosting it as a proper project. Also, this one might be a better alternative: https://github.com/AtsushiSakai/rosbag_to_csv

Or simply rostopic echo -b file.bag -p /topic will work for some simple data types. The best is probably the really neat rosbag_pandas package for python that also includes a bag2csv.py tool

Hope this helps @Shivani1796

@Shivani1796
Copy link

Shivani1796 commented Dec 28, 2019 via email

@eldiabloavis
Copy link

I am new to working with rosbag files and was having a hard time, trying to get rosbag_pandas to work. This script was a lifesaver. Thanks @marc-hanheide

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment