Creating new proof-of-concept experimental package bagfs.

This commit is contained in:
Jeremy Leibs 2009-12-05 20:26:22 +00:00
parent 0ec6214592
commit 055d2fddad
6 changed files with 208 additions and 0 deletions

View File

@ -54,6 +54,9 @@ python-numpy:
rhel: python-numpy
arch: python-numpy
macports: py25-numpy
python-fuse:
ubuntu: python-fuse
debian: python-fuse
python-scipy:
ubuntu: python-scipy
debian: python-scipy

View File

@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
# Set the build type. Options are:
# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage
# Debug : w/ debug symbols, w/o optimization
# Release : w/o debug symbols, w/ optimization
# RelWithDebInfo : w/ debug symbols, w/ optimization
# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries
#set(ROS_BUILD_TYPE RelWithDebInfo)
rosbuild_init()
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#uncomment if you have defined messages
#rosbuild_genmsg()
#uncomment if you have defined services
#rosbuild_gensrv()
#common commands for building c++ executables and libraries
#rosbuild_add_library(${PROJECT_NAME} src/example.cpp)
#target_link_libraries(${PROJECT_NAME} another_library)
#rosbuild_add_boost_directories()
#rosbuild_link_boost(${PROJECT_NAME} thread)
#rosbuild_add_executable(example examples/example.cpp)
#target_link_libraries(example ${PROJECT_NAME})

View File

@ -0,0 +1 @@
include $(shell rospack find mk)/cmake.mk

View File

@ -0,0 +1,30 @@
/**
\mainpage
\htmlinclude manifest.html
\b bagfs is ...
<!--
In addition to providing an overview of your package,
this is the section where the specification and design/architecture
should be detailed. While the original specification may be done on the
wiki, it should be transferred here once your package starts to take shape.
You can then link to this documentation page from the Wiki.
-->
\section codeapi Code API
<!--
Provide links to specific auto-generated API documentation within your
package that is of particular interest to a reader. Doxygen will
document pretty much every part of your code, so do your best here to
point the reader to the actual API.
If your codebase is fairly large or has different sets of APIs, you
should use the doxygen 'group' tag to keep these APIs together. For
example, the roscpp documentation has 'libros' group.
-->
*/

View File

@ -0,0 +1,19 @@
<package>
<description brief="bagfs">
Experimental package to create a filesystem representation of a bagfile.
</description>
<author>Jeremy Leibs</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/bagfs</url>
<depend package="rospy"/>
<depend package="roslib"/>
<depend package="std_msgs"/>
<depend package="rosrecord"/>
<!-- We use fuse to create the filesystem -->
<rosdep name="python-fuse"/>
</package>

View File

@ -0,0 +1,125 @@
#!/usr/bin/env python
PKG = 'bagfs'
import roslib; roslib.load_manifest(PKG)
import rospy
import rosrecord
import os, stat, errno, sys
import fuse
import subprocess
from fuse import Fuse
from time import time
fuse.fuse_python_api = (0, 2)
class MyStat(fuse.Stat):
def __init__(self):
self.st_mode = 0
self.st_ino = 0
self.st_dev = 0
self.st_nlink = 0
self.st_uid = 0
self.st_gid = 0
self.st_size = 0
self.st_atime = 0
self.st_mtime = 0
self.st_ctime = 0
class BagFS(Fuse):
def __init__(self, bag, version, usage, dash_s_do):
Fuse.__init__(self, version=version, usage=usage, dash_s_do=dash_s_do)
self.msgs = {}
self.sizecache = {}
for i,(topic, msg, t) in enumerate(rosrecord.logplayer(bag, raw=True)):
cdir = self.msgs
for ns in topic.lstrip('/').split('/'):
if not ns in cdir:
self.msgs[ns] = {}
cdir=cdir[ns]
cdir["%.6d"%i] = (topic,msg,t)
def lookup(self, path):
cdir = self.msgs
if path == '/':
return cdir
p = path.split('/')
p.remove('')
for ns in p[:-1]:
if ns in cdir and isinstance(cdir[ns], dict):
cdir=cdir[ns]
else:
return None
if p[-1] in cdir:
return cdir[p[-1]]
else:
return None
def getattr(self, path):
st = MyStat()
st.st_atime = int(time())
st.st_mtime = st.st_atime
st.st_ctime = st.st_atime
fil = self.lookup(path)
if fil is None:
return -errno.ENOENT
elif isinstance(fil, dict):
st.st_mode = stat.S_IFDIR | 0755
st.st_nlink = len(fil)
else:
st.st_mode = stat.S_IFREG | 0444
st.st_nlink = 1
st.st_mtime = int(fil[2].to_sec())
st.st_ctime = st.st_mtime
if path in self.sizecache:
st.st_size = self.sizecache[path]
else:
st.st_size = 1
return st
def readdir(self, path, offset):
yield fuse.Direntry('.')
yield fuse.Direntry('..')
dir = self.lookup(path)
for leaf in dir:
yield fuse.Direntry(leaf)
def open(self, path, flags):
msg = self.lookup(path)
accmode = os.O_RDONLY
if (flags & accmode) != os.O_RDONLY:
return -errno.EACCES
m = msg[1][4]()
m.deserialize(msg[1][1])
disp = roslib.message.strify_message(m) + '\n'
self.sizecache[path] = len(disp)
return disp
def read(self, path, size, offset, fh):
return fh[offset:offset+size]
def main():
usage="""
Userspace script runner
""" + Fuse.fusage
bag = sys.argv[1]
server = BagFS(bag, version="%prog " + fuse.__version__,
usage=usage,
dash_s_do='setsingle')
server.parse(errex=1)
server.main()
if __name__ == '__main__':
main()