ros / ros_comm

ROS communications-related packages, including core client libraries (roscpp, rospy, roslisp) and graph introspection tools (rostopic, rosnode, rosservice, rosparam).
http://wiki.ros.org/ros_comm
752 stars 913 forks source link

rosbag: allow writing message to rosbag without knowing its type (C++) #1417

Open fzimmerm opened 6 years ago

fzimmerm commented 6 years ago

Hi,

I'm using the C++ rosbag API, and want to delete a single message from a bag. For this, I was thinking of opening the bag in Read mode, opening another bag inWrite mode, and then iterate over all MessageInstance in a View of the original bag and write them to the new bag, except for messages with the same topic, type and time as the message I want to delete. But since the bag may contain messages of unknown types, I cannot instantiate the MessageInstance. I saw that MessageInstance has a method for writing it into a Stream, and that Bag has a private method void Bag::write(char const* s, std::streamsize n), so in theory it should be possible to serialize all MessageInstance into a Stream and writing it into the new bag, without knowing the individual message types, if the write method weren't private.

Long story short, it would be very useful to have a method to transfer messages between bags without knowing each message's type, in C++ (I think in python this doesn't pose a problem).

ibtaylor commented 6 years ago

auto msg = message_instance.instantiate<topic_tools::ShapeShifter>() You should be able to then write that to another bag without having the c++ message type.

Unfortunately, the message instance only has when the message was written "bag write time" and not the "message time". For that, if you want to handle arbitrary types, you might want to look into something like ros_type_introspection.

fzimmerm commented 6 years ago

Thanks a lot for the hint, this should solve my problem! I'll post more feedback as soon as I have the time to try it out.

fzimmerm commented 6 years ago

I've tried writing all messages to a new bag using topic_tools::ShapeShifter. The resulting bag looks fine (same size, rosbag info output looks correct), but when iterating over it using a rosbag::View it will suddenly throw a ros::serialization::StreamOverrunException. This isn't the case with the original bag. The same thing happened when using python to rewrite the bag.

cwecht commented 5 years ago

@fzimmerm could you provide a minimal example of your code and a (ideally small) rosbag which reproduce this issue?

karthiknit commented 3 years ago

@fzimmerm Could you post a sample code here for writing all messages to a bag using topic_tools::ShapeShifter?

fzimmerm commented 3 years ago

@cwecht @karthiknit Sorry but since I created this issue I've changed position, don't have access to the code in question anymore and am working on a topic unrelated to ROS. Thank you anyway!

shaozu commented 3 years ago
for(rosbag::MessageInstance const mi : view)
{
    out_bag.write(mi.getTopic(), mi.getTime(), mi);
}

Just found this will do the job.

karthiknit commented 3 years ago

I think this does the job only when you are reading from one bag and writting data to other bag

shaozu commented 3 years ago

Yes, and I guess this will meet the requirement of fzimmerm.

fjandrad commented 1 year ago

I can confirm that solution by @shaozu works. I am able to ready a bag separate topics between the ones I want the ones I dont want and then write to the new bag only the ones I desire.