如何基于参数各异的多rosbag文件在Jupyter Notebook逐次绘图
完整流程:用Jupyter Notebook分析多参数rosbag并绘图
我平时处理多rosbag文件分析的需求时,一般会按环境准备→单bag解析→批量处理→按需绘图这个流程来,结合你的情况(自定义msg、多参数、公共变量绘图),给你一步步拆解:
一、前期环境与准备
首先得确保Notebook里能正常调用ROS相关工具和数据处理库:
- 先在终端激活你的ROS工作空间(
source ~/your_ws/devel/setup.bash),再启动Jupyter Notebook(jupyter notebook),这样才能导入自定义的msg和rosbag模块。 - 安装必要的Python库:
pip install pandas matplotlib rospy rosbag - 确认自定义msg已经编译成功,在Notebook里可以通过
from your_package.msg import YourCustomMsg导入,要是导入报错,检查工作空间是否激活、setup.py有没有配置msg路径。
二、编写通用的rosbag解析函数
因为你的每个bag对应不同的msg,但有公共变量,所以可以写一个通用函数,根据传入的topic和msg类型,提取需要的字段(包括公共字段和该bag特有的参数):
import rosbag import pandas as pd from your_package.msg import MsgType1, MsgType2 # 替换成你的自定义msg类型 def parse_bag(bag_path, target_topic, msg_class, common_fields, unique_fields): """ 解析单个rosbag文件,提取指定字段 :param bag_path: rosbag文件路径 :param target_topic: 要订阅的topic :param msg_class: 对应的自定义msg类 :param common_fields: 所有bag都有的公共字段列表(比如["timestamp", "velocity"]) :param unique_fields: 当前bag特有的字段列表(比如["temperature", "pressure"]) :return: 包含所有字段的DataFrame """ bag = rosbag.Bag(bag_path, 'r') data = [] for topic, msg, t in bag.read_messages(topics=[target_topic]): # 提取时间戳(转换成秒,方便绘图) timestamp = t.to_sec() # 组装字段字典 entry = {"timestamp": timestamp} # 提取公共字段 for field in common_fields: entry[field] = getattr(msg, field) # 提取当前bag特有字段 for field in unique_fields: entry[field] = getattr(msg, field) data.append(entry) bag.close() return pd.DataFrame(data)
这个函数的好处是,每个bag只需要传入对应的msg类、公共字段和特有字段,就能统一转换成DataFrame,方便后续处理。
三、批量处理多个rosbag
把所有bag的信息整理成一个配置列表,然后循环调用上面的解析函数,把每个bag的数据存起来:
# 配置每个bag的信息:路径、topic、msg类、公共字段、特有字段 bag_configs = [ { "name": "bag_01", "path": "/path/to/your/bag1.bag", "topic": "/sensor/data1", "msg_class": MsgType1, "common_fields": ["velocity", "acceleration"], "unique_fields": ["temperature"] }, { "name": "bag_02", "path": "/path/to/your/bag2.bag", "topic": "/sensor/data2", "msg_class": MsgType2, "common_fields": ["velocity", "acceleration"], "unique_fields": ["pressure", "humidity"] } # 继续添加其他bag的配置 ] # 批量解析,存到字典里,key是bag名称,value是对应的DataFrame bag_data_dict = {} for config in bag_configs: print(f"正在解析 {config['name']}...") df = parse_bag( config["path"], config["topic"], config["msg_class"], config["common_fields"], config["unique_fields"] ) bag_data_dict[config["name"]] = df
这样所有bag的数据都存在bag_data_dict里,随时可以调用。
四、按需绘图
接下来就可以根据需求绘图了,分两种常见场景:
1. 公共变量跨bag对比绘图
比如对比多个bag里的velocity随时间的变化:
import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) # 遍历每个bag的数据,绘制velocity曲线 for bag_name, df in bag_data_dict.items(): plt.plot(df["timestamp"], df["velocity"], label=bag_name) plt.xlabel("Time (s)") plt.ylabel("Velocity (m/s)") plt.title("Velocity Comparison Across Multiple Bags") plt.legend() plt.grid(True) plt.show()
2. 单个bag的多参数分析绘图
比如针对bag_02,同时绘制acceleration和pressure的时间序列图:
df_bag2 = bag_data_dict["bag_02"] fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=True) # 第一个子图:acceleration ax1.plot(df_bag2["timestamp"], df_bag2["acceleration"], color="blue") ax1.set_ylabel("Acceleration (m/s²)") ax1.set_title("Acceleration and Pressure of bag_02") ax1.grid(True) # 第二个子图:pressure ax2.plot(df_bag2["timestamp"], df_bag2["pressure"], color="red") ax2.set_xlabel("Time (s)") ax2.set_ylabel("Pressure (Pa)") ax2.grid(True) plt.tight_layout() plt.show()
3. 公共变量与特有变量的关联分析
比如看bag_01里velocity和temperature的相关性:
df_bag1 = bag_data_dict["bag_01"] plt.figure(figsize=(8, 6)) plt.scatter(df_bag1["velocity"], df_bag1["temperature"], alpha=0.5) plt.xlabel("Velocity (m/s)") plt.ylabel("Temperature (°C)") plt.title("Velocity vs Temperature in bag_01") plt.grid(True) plt.show()
五、一些实用小贴士
- 如果rosbag文件特别大,可以在解析的时候分批读取,或者只提取需要的时间段的数据(在
bag.read_messages里加上start_time和end_time参数),避免内存溢出。 - 时间戳如果是ROS的
rostime,可以用t.to_sec()转换成秒,方便和其他时间数据对齐。 - 如果自定义msg里有嵌套结构(比如
msg.header.stamp),可以用getattr嵌套提取,比如getattr(msg.header, "stamp").to_sec()。 - 绘图时可以用
seaborn库让图表更美观,比如import seaborn as sns; sns.set_style("whitegrid")。
内容的提问来源于stack exchange,提问作者HalfBloodPrince7
相关产品推荐
相关产品推荐

