这篇文字想通过在自己的机器上查找rosbag的源码在哪里(而不是通过google搜索),来和大家分享一些ros和python的常用命令,了解一下rosbag的调用过程。
怎么查到源码在哪里
当然我们可以直接上ros的官网去查看,路径在这里:https://wiki.ros.org/rosbag
本着程序员的好奇心,我们也可以不看官方文档,自己先去探索一下:
我们先来看看我们日常用的rosbag是个啥:
$ which rosbag
可以看到我们日常使用的rosbag命令的位置在:
/opt/ros/noetic/bin/rosbag
然后我们在看下这个路径是个啥文件:
$ file /opt/ros/noetic/bin/rosbag
唉,发现这个命令居然是个python脚本
进一步的,我们来看下这个python脚本的内容是什么
$ code /opt/ros/noetic/bin/rosbag ## 这里用vscode打开文件来查看
哇,这个python脚本如此简单粗暴,只有一个导入和调用。
既然它是一个python包,那我们用pip来看看它在哪里:
我们起码看到了两个有用的信息:
● Home-page: https://wiki.ros.org/rosbag
, 有了这个,我们已经可以上官网去看了
● Location: /opt/ros/noetic/lib/python3/dist-packages
, 有了这个,我们可以去看下rosbag的python代码是啥
去官网查资料就没啥好说的了,下面说一下自己看rosbag的python代码:
我们用vscode打开一下rosbag路径:
$ code /opt/ros/noetic/lib/python3/dist-packages/rosbag
可以看到,python代码的文件还是比较少的。
在上面,我们看到,/opt/ros/noetic/bin/rosbag文件中执行的是rosbag.rosbagmain()
因此我们主要看下这个函数:
函数在/opt/ros/noetic/lib/python3/dist-packages/rosbag/rosbag_main.py
def rosbagmain(argv=None):
cmds = RosbagCmds()
cmds.add_cmd('record', record_cmd, "Record a bag file with the contents of specified topics.")
cmds.add_cmd('info', info_cmd, 'Summarize the contents of one or more bag files.')
cmds.add_cmd('play', play_cmd, "Play back the contents of one or more bag files in a time-synchronized fashion.")
cmds.add_cmd('check', check_cmd, 'Determine whether a bag is playable in the current system, or if it can be migrated.')
cmds.add_cmd('fix', fix_cmd, 'Repair the messages in a bag file so that it can be played in the current system.')
cmds.add_cmd('filter', filter_cmd, 'Filter the contents of the bag.')
cmds.add_cmd('compress', compress_cmd, 'Compress one or more bag files.')
cmds.add_cmd('decompress', decompress_cmd, 'Decompress one or more bag files.')
cmds.add_cmd('reindex', reindex_cmd, 'Reindexes one or more bag files.')
if sys.platform != 'win32':
cmds.add_cmd('encrypt', encrypt_cmd, 'Encrypt one or more bag files.')
cmds.add_cmd('decrypt', decrypt_cmd, 'Decrypt one or more bag files.')
if argv is None:
argv = sys.argv
if '-h' in argv or '--help' in argv:
argv = [a for a in argv if a != '-h' and a != '--help']
argv.insert(1, 'help')
if len(argv) > 1:
cmd = argv[1]
else:
cmd = 'help'
try:
if cmd in cmds:
cmds[cmd](argv[2:])
else:
cmds['help']([cmd])
except KeyboardInterrupt:
pass
在这里,我们看到熟悉的rosbag命令的影子,比如 rosbag info, rosbag play等
看一下代码,可以知道这个函数其实就是组织了各个子命令,下面我们以play这个子命令来看一下流程:
play 子命令调用的是play_cmd(argv)
这个函数,
而看了这个函数内部的实现,它主要干了两件事:
- 解析参数,比如 --rate, --duration等
- 找到rosbag这个ros node:
playpath = roslib.packages.find_node('rosbag', 'play')
生成一个启动该rosnode的shell命令, 比如rosbag play --rate 2 --duration 3 xxx.bag
, 然后使用process = subprocess.Popen(cmd)
去执行这个shell命令,启动这个rosnode
到这里,我们先来总结一下前面的内容:
- 我们日常使用的rosbag命令,其实是一个pyhton脚本
- 这个python脚本位于一个叫rosbag的python package中
- 这个python脚本其实并没有实现具体的功能,它只是负责解析参数,最后启动一个叫做rosbag的ros节点
下面我们来看下这个ros节点:
既然是ros节点,我们来切换到该节点的目录下:
$ roscd rosbag
然后,我们来看看这个节点的信息:
是不是很熟悉,我们来看下package.xml
这不就是我们要找的rosbag的源码路径了吗。
经过这一波折腾,是不是熟悉了一些ros和python的命令了呢?
当然,如果你不想折腾,直接google, “rosbag source code” 就行啦。