You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于参数各异的多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:19:00