[Documentation] [TitleIndex] [WordIndex

The rosbag migration system allows you to fix outdated bags once messages have changed. This can be done using the command line tools rosbag check and rosbag fix. The system works using plugin-based migration rules. These rules can be exported by any package, though it is nice to keep the migration rules in the same package as the messages themselves.

Rule Files

Rule files define one or more Python classes which subclass rosbagmigration.MessageUpdateRule and override the appropriate fields and functions. Since they take a specific form, we use the extention .bmr (bag migration rule) in place of the typical .py extension.

The following fields must be overridden:

The following method must be overridden:

The update function

For the most part just about all of the rule definition will be generated for you by rosbag check or makerule.py. The place where the most user intervention is necessary is the update function. The update function takes two inputs: old_msg, and new_msg. The intent is to fill in the fields of new_msg appropriately with a combination of default values or values moved over from old_msg.

There are a few important helper classes to make this substantially easier:

An example rule file for a message and its sub-message. Note: With the exception of changing the valid member to True, this entire file was generated by following the directions in Migrating Messages.

class update_mypkg_MyMsg_cdeceeac6a1a98788dbcb8bf5f31b49b(MessageUpdateRule):
        old_type = "mypkg/MyMsg"
        old_full_text = """
MySubMsg data

================================================================================
MSG: mypkg/MySubMsg
int32 field1
string field2
"""

        new_type = "mypkg/MyMsg"
        new_full_text = """
MySubMsg data
MySubMsg more_data

================================================================================
MSG: mypkg/MySubMsg
int32 field1
string field2
float64 another_field
"""

        order = 0
        migrated_types = [("MySubMsg","MySubMsg")]

        valid = True

        def update(self, old_msg, new_msg):
                self.migrate(old_msg.data, new_msg.data)
                #No matching field name in old message
                new_msg.more_data = self.get_new_class('MySubMsg')()

class update_mypkg_MySubMsg_4b12e5ff694b0e2a31b2ea9e0bd900f4(MessageUpdateRule):
        old_type = "mypkg/MySubMsg"
        old_full_text = """
int32 field1
string field2
"""

        new_type = "mypkg/MySubMsg"
        new_full_text = """
int32 field1
string field2
float64 another_field
"""

        order = 0
        migrated_types = []

        valid = True

        def update(self, old_msg, new_msg):
                new_msg.field1 = old_msg.field1
                new_msg.field2 = old_msg.field2
                #No matching field name in old message
                new_msg.another_field = 0.

Migrating Messages

Preferred Approach to Making Rules

Rather than generating rules from bag files after the fact, the preferred approach is to generate the necessary rules at the time that the message is migrated. There are 2 scripts for making this fairly easy to do. savemsg.py and makerule.py

savemsg.py allows you to save a full message definition in a temporary file so that when you modify it you can create a rule between the original and the new version.

makerule.py generates a migration rule between a saved instance of a message and a message currently defined in the system. It is functionally equivalent to creating a recording, except that the file format is human readable for convenience.

For example, in a tree at a revision that contains the old copy of your message:

$ roscd mypkg
$ rosmake mypkg
$ rosrun rosbag savemsg.py mypkg/MyMsg > MyMsg.saved

Now, edit your Message, or change revisions to the revision containing the new copy of your message.

Make sure to rebuild in the tree with the new definition, and then you can generate a rule:

$ rosmake mypkg
$ rosrun rosbag makerule.py MyMsg.saved myrule.bmr

If you have moved the message, it will prompt you for the new location.

Now you can edit the file myrule.bmr according to Rule Files.

Finally, if you want the rule to be permanently exported for people to use, add the following export to you manifest file:

<export>
  <rosbag migration_rule_file="myrule.bmr"/>
</export>

This will cause the rule file to be automatically loaded whenever the message migrator is instantiated.

NOTE: in order for a plugin to be exported correctly, you must depend on the package the plugin is used for. In this case your package MUST have a dependency on rosbag to export migration rules.

<depend package="rosbag"/>

<run_depend>rosbag</run_depend>

As of Groovy you can also avoid the dependency on rosbag and instead depend on the new package rosbag_migration_rule. If you do so the export tag must be names like this:

<export>
  <rosbag_migration_rule rule_file="myrule.bmr"/>
</export>

Alternative Approach to Making Rules

rosbag check can also be used to populate most of the rule templates for you so long as the type names still match.

To generate rules:

$ rosbag check in.bag -g myrules.bmr

Note: Using this functionality is not generally advised for creating permanent rules to check into the system. Creating rules directly from arbitrarily old bag files is likely to skip intermediate changes and lead to ordering confusion. However, if a bag is missing rules, this is intended to be the quickest pathway to making it functional.

At this point, you will need to edit myrules.bmr by hand. See Rule Files for more info.

To make sure your rules are sufficient, you can now pass the rule file into rosbag check explicitly:

$ rosbag check in.bag myrules.bmr

2019-11-16 13:15