如何在不生成新文件前提下合并两个rosbag

文章讲述了如何使用ROS的bagmode::BagMode::Append模式来实现对同一个ROSbag文件的读写操作,特别是在合并两个bag文件或将处理结果写回原bag时的处理方法。通过分析rosbag的C++源码,发现openReadWrite()函数以r+b模式打开文件,允许读写操作。
摘要由CSDN通过智能技术生成

将两个rosbag文件合并到一个新的robag文件里是很容易的,open两个源文件时指定bagmode::BagMode::Read(或BagMode::Read),然后read,open保存合并结果的新文件时指定bagmode::BagMode::Write(BagMode::Write),不用多说,如果将两个bag合并将结果保存在其中一个bag里,或者读取一个bag中的数据输入模型进行推理,然后把识别结果写回到此bag中,这些操作处理的本质涉及到对同一bag文件的同时读写处理,该怎么做呢?

查了一下网上资料,都是说怎么单独读和写bag文件的没有用,查看ros.org上文档也没有用的信息,只好去翻看rosbag的源码(C++源码需要到https://github.com/ros/ros_comm这里下载,ros安装时安装的都是C++代码编译成出来的so库以及对应的python代码,所以ros安装目录下只能看python版的代码),发现还有个BagMode就是BagMode::Append,看了一下相关代码,用Append这种模式就能解决同时读写同一个bag文件的问题:

void Bag::open(string const& filename, uint32_t mode) {
    mode_ = (BagMode) mode;

    if (mode_ & bagmode::Append)
        openAppend(filename);
    else if (mode_ & bagmode::Write)
        openWrite(filename);
    else if (mode_ & bagmode::Read)
        openRead(filename);
    else
        throw BagException((format("Unknown mode: %1%") % (int) mode).str());

    // Determine file size
    uint64_t offset = file_.getOffset();
    seek(0, std::ios::end);
    file_size_ = file_.getOffset();
    seek(offset);
}

void Bag::openRead(string const& filename) {
    file_.openRead(filename);

    readVersion();

    switch (version_) {
    case 102: startReadingVersion102(); break;
    case 200: startReadingVersion200(); break;
    default:
        throw BagException((format("Unsupported bag file version: %1%.%2%") % getMajorVersion() % getMinorVersion()).str());
    }
}

void Bag::openWrite(string const& filename) {
    file_.openWrite(filename);

    startWriting();
}

void Bag::openAppend(string const& filename) {
    file_.openReadWrite(filename);

    readVersion();

    if (version_ != 200)
        throw BagException((format("Bag file version %1%.%2% is unsupported for appending") % getMajorVersion() % getMinorVersion()).str());

    startReadingVersion200();

    // Truncate the file to chop off the index
    file_.truncate(index_data_pos_);
    index_data_pos_ = 0;

    // Rewrite the file header, clearing the index position (so we know if the index is invalid)
    seek(file_header_pos_);
    writeFileHeaderRecord();

    // Seek to the end of the file
    seek(0, std::ios::end);
}

我们可以看到当mode是BagMode::Append时,open()调用的openAppend()函数里第一句就是

file_.openReadWrite(filename);

这个openReadWrite()其实就是以r+b方式打开文件,实现代码在chunked_file.cpp里:

ChunkedFile::ChunkedFile() :
    file_(NULL),
    offset_(0),
    compressed_in_(0),
    unused_(NULL),
    nUnused_(0)
{
    stream_factory_ = boost::make_shared<StreamFactory>(this);
}

ChunkedFile::~ChunkedFile() {
    close();
}

void ChunkedFile::openReadWrite(string const& filename) { open(filename, "r+b"); }
void ChunkedFile::openWrite    (string const& filename) { open(filename, "w+b");  }
void ChunkedFile::openRead     (string const& filename) { open(filename, "rb");  }

void ChunkedFile::open(string const& filename, string const& mode) {
    // Check if file is already open
    if (file_)
        throw BagIOException((format("File already open: %1%") % filename_.c_str()).str());

    // Open the file
    if (mode == "r+b") {
        // check if file already exists
        #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
            fopen_s( &file_, filename.c_str(), "r" );
        #else
            file_ = fopen(filename.c_str(), "r");
        #endif
        if (file_ == NULL)
            // create an empty file and open it for update
            #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
                fopen_s( &file_, filename.c_str(), "w+b" );
            #else
                file_ = fopen(filename.c_str(), "w+b");
            #endif
        else {
            if (fclose(file_) != 0)
              throw BagIOException((format("Error closing file: %1%") % filename.c_str()).str());

            // open existing file for update
            #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
                fopen_s( &file_, filename.c_str(), "r+b" );
            #else
                file_ = fopen(filename.c_str(), "r+b");
            #endif
        }
    }
    else

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arnold-FY-Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值