Search code examples
pythonlinuxioros

Extract Data from ROSbag


I'm pretty new to python and just need to be able to extract raw data messages from a rosbag so that I can manipulate it with algorithms to look for patterns in LiDAR data.

I found a script on github to extract data from a rosbag but get this error (running from terminal in Ubuntu 16.04):

adam@manatee:~/workspace/TORC/LiDAR$ python ExtractDataROSbag.py 2017-02-27-09-35-59_0.bag
[OK] Found bag: 2017-02-27-09-35-59_0.bag
Traceback (most recent call last):
  File "ExtractDataROSbag.py", line 130, in <module>
    run()
  File "ExtractDataROSbag.py", line 40, in run
    bag = rosbag.Bag(inputFileName)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rosbag/bag.py", line 173, in __init__
    self._open(f, mode, allow_unindexed)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rosbag/bag.py", line 1096, in _open
    if   mode == 'r': self._open_read(f, allow_unindexed)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rosbag/bag.py", line 1118, in _open_read
    self._file     = open(f, 'rb')
IOError: [Errno 2] No such file or directory: '2017-02-27-09-35-59_0.bag'

It seem to iterate through the beginning of the code and recognizes the bag file, printing "Found Bag" and even setting the variables after that, but then the error begins.

The full code of the script I am running is as follows:

#!/usr/bin/python

# Copyright 2010 Ankur Sinha
# Author: Ankur Sinha
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# File : extractRawInfo.py
#

import rosbag
import sys
import os
import pickle

# Global variable for input file name

def run():
    """
    Main run method. Calls other helper methods to get work done
    """

    if len(sys.argv) != 2:
        sys.stderr.write('[ERROR] This script only takes input bag file as argument.n')
    else:
        inputFileName = sys.argv[1]
        print "[OK] Found bag: %s" % inputFileName

        bag = rosbag.Bag(inputFileName)
        topicList = readBagTopicList(bag)

        while True:
            if len(topicList) == 0:
                print "No topics in list. Exiting"
                break
            selection  = menu(topicList)

            if selection == -92:
                print "[OK] Printing them all"
                for topic in topicList:
                    extract_data(bag, topic, inputFileName)
                break
            elif selection == -45:
                break
            else:
                topic = topicList[selection]
                extract_data(bag, topic, inputFileName)
                topicList.remove(topicList[selection])

        bag.close()

def extract_data (bag, topic, inputFileName):
    """
    Spew messages to a file

    args:
        topic -> topic to extract and print to txt file
    """

    outputFileName = os.path.splitext(os.path.split(inputFileName)[1])[0] + topic.replace("/","-") + ".txt"
    print "[OK] Printing %s" % topic
    print "[OK] Output file will be called %s." % outputFileName

    outputFh = open(outputFileName, "w")

    for topic, msg, t in bag.read_messages(topics=topic):
        pickle.dump(msg,outputFh)

    outputFh.close()
    print "[OK] DONE"

def menu (topicList):
    """
    Print the user menu and take input

    args:
        topicList: tuple containing list of topics

    returns:
        selection: user selection as integer
    """

    i = 0
    for topic in topicList:
        print '[{0}] {1}'.format(i, topic)
        i = i+1
    if len(topicList) > 1:
        print '[{0}] Extract all'.format(len(topicList))
        print '[{0}] Exit'.format(len(topicList) + 1)
    else:
        print '[{0}] Exit'.format(len(topicList))

    while True:
        print 'Enter a topic number to extract raw data from:'
        selection = raw_input('>>>')
        if int(selection) == len(topicList):
            return -92 # print all
        elif int(selection) == (len(topicList) +1):
            return -45 # exit
        elif (int(selection) < len(topicList)) and (int(selection) >= 0):
            return int(selection)
        else:
            print "[ERROR] Invalid input"

def readBagTopicList(bag):
    """
    Read and save the initial topic list from bag
    """
    print "[OK] Reading topics in this bag. Can take a while.."
    topicList = []
    for topic, msg, t in bag.read_messages():
        if topicList.count(topic) == 0:
            topicList.append (topic)

    print '{0} topics found:'.format(len(topicList))
    return topicList

if __name__ == "__main__":
    run()

Solution

    1. Ensure that the named file really does exist. Copy the filename out of the error message and ask your system to find it. Don't retype the name, because if you introduced an error the first time, you may do it again.

    2. If the file really is there, try providing the full path to the .bag file on the command line.