Ask Your Question
4

How to play rosbag file from node

asked 2014-03-26 04:44:47 -0500

TFinleyosu gravatar image

Long story short, I am trying to play a bag file from a node and mimic the same functionality of the following:

rosbag play -l recorded1.bag

Before I dive in to the rosbag API, I thought I'd ask the question if there was a simpler way than using the API, which I am not completely familiar with.

If the API was the way, I was thinking something like this:

import rosbag
bag = rosbag.Bag('test.bag')
% Loop
    for topic, msg, t in bag.read_messages(topics=['chatter', 'numbers']):
        %Publish Messages

Am I on the right track?

Cheers

edit retag flag offensive close merge delete

Comments

1

curiosity: Why would you want to implement that yourself? You can start rosbag like this also as node via launch file...

Wolf gravatar imageWolf ( 2014-03-26 06:27:26 -0500 )edit
2

I am doing a research study and I need to be able to play a random bag file of Kinect data when a button is pressed in another node. The button will be used many times and I need to avoid any terminal commands. Am I able to launch a launch file from within a node?

TFinleyosu gravatar imageTFinleyosu ( 2014-03-26 06:57:16 -0500 )edit

Yes the rosbag API seems to be the straight forward solution in this case I think. YOU could call into the rosbag via system command, but you would have to open the rosbag after every button press, so I think the application would be very slow and unresponsive...

Wolf gravatar imageWolf ( 2014-03-26 07:46:51 -0500 )edit

Thanks for the help Wolf

TFinleyosu gravatar imageTFinleyosu ( 2014-03-27 04:16:33 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
6

answered 2014-03-27 03:42:52 -0500

timm gravatar image

updated 2014-03-27 03:46:21 -0500

The rosbag play application itself is implemented in C++: play.cpp

The code relevant to publishing messages can be found in the method Player::publish(). The C++ file also contains code for pausing and resuming playback, console output etc., but maybe you can use this code to get a rough idea: player.cpp

I'd expect Python to give slightly worse performance compared to C++ if you plan to play large bagfiles (e.g. containing camera images).


Edit, to answer your question: I believe there is no other way than either

  • using the C++ API (should provide best performance)
  • using the Python API
  • invoking "rosbag play" using a system() command.
edit flag offensive delete link more

Comments

Great point. Thanks for the guidance. I will get to this soon and post my solution for reference.

TFinleyosu gravatar imageTFinleyosu ( 2014-03-27 04:16:18 -0500 )edit
2

answered 2014-03-31 15:56:31 -0500

TFinleyosu gravatar image

Here was my solution for future reference. Please feel free to critique it.

#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/PointCloud2.h>
#include "std_msgs/String.h"
#include <boost/foreach.hpp>
#include <sstream>
#include <ros/package.h>

int main(int argc, char **argv) {
    ros::init(argc, argv, "publish_scene");

    ros::NodeHandle n;

    ros::Publisher d_info_pub = n.advertise<sensor_msgs::CameraInfo>("scene/depth/camera_info", 1);
    ros::Publisher d_points_pub = n.advertise<sensor_msgs::PointCloud2>("scene/depth/points", 1);
    ros::Publisher rgb_info_pub = n.advertise<sensor_msgs::CameraInfo>("scene/rgb/camera_info", 1);
    ros::Publisher rgb_image_pub = n.advertise<sensor_msgs::Image>("scene/rgb/image", 1);
    ros::Rate loop_rate(10);

  std::string package_path = ros::package::getPath("pick");
  std::string scene_path;

  while (ros::ok()){

    int scene_number;
    if (n.getParam("/scene/number", scene_number))
    {
      ROS_INFO("Scene Number: %i \n",scene_number);
      std::stringstream sstm;
      if (scene_number > 9)
        sstm << package_path << "/scenes/scene_" << scene_number << ".bag";
      else
        sstm << package_path << "/scenes/scene_0" << scene_number << ".bag";

      scene_path = sstm.str();
    }
    else
    {
      ROS_INFO("rosparam /scene/number not set");
      break;
    }

    rosbag::Bag bag;
    bag.open(scene_path, rosbag::bagmode::Read);

    std::string depth_cam_info = "/camera/depth_registered/camera_info";
    std::string depth_points = "/camera/depth_registered/points";
    std::string rgb_cam_info = "/camera/rgb/camera_info";
    std::string rgb_cam_image = "/camera/rgb/image_color";

    std::vector<std::string> topics;
    topics.push_back(depth_cam_info);
    topics.push_back(depth_points);
    topics.push_back(rgb_cam_info);
    topics.push_back(rgb_cam_image);

    rosbag::View view(bag, rosbag::TopicQuery(topics));

    BOOST_FOREACH(rosbag::MessageInstance const m, view)
    {
      if (m.getTopic() == depth_cam_info) 
      {
        sensor_msgs::CameraInfo::ConstPtr d_info_ptr = m.instantiate<sensor_msgs::CameraInfo>();
        if (d_info_ptr != NULL)
          d_info_pub.publish(*d_info_ptr);
      }

      if (m.getTopic() == depth_points) 
      {
        sensor_msgs::PointCloud2::ConstPtr d_points_ptr = m.instantiate<sensor_msgs::PointCloud2>();
        if (d_points_ptr != NULL)
          d_points_pub.publish(*d_points_ptr);
      }

      if (m.getTopic() == rgb_cam_info) 
      {
        sensor_msgs::CameraInfo::ConstPtr rgb_info_ptr = m.instantiate<sensor_msgs::CameraInfo>();
        if (rgb_info_ptr != NULL)
          rgb_info_pub.publish(*rgb_info_ptr);
      }

      if (m.getTopic() == rgb_cam_image) 
      {
        sensor_msgs::Image::ConstPtr rgb_image_ptr = m.instantiate<sensor_msgs::Image>();
        if (rgb_image_ptr != NULL)
          rgb_image_pub.publish(*rgb_image_ptr);
      }

    }

  bag.close();
  ros::spinOnce();
  loop_rate.sleep();

  }

}
edit flag offensive delete link more

Comments

1

Thanks for sharing :)

dj0405 gravatar imagedj0405 ( 2015-02-27 11:57:45 -0500 )edit
1

In addition to excellent answer above, the rosbag API page links to some cookbook code snippets.

Will Chamberlain gravatar imageWill Chamberlain ( 2016-08-30 19:34:47 -0500 )edit

Hey does the above code preserve the desired output frequency on various topics?? Say our bag has 2 topics and if there are more messages in one topic than the other one. Does this approach publish data on these two topics at different( but appropriate) frequency rates ?

hannavaj gravatar imagehannavaj ( 2018-12-12 16:30:42 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2014-03-26 04:44:47 -0500

Seen: 4,558 times

Last updated: Mar 31 '14