0
$\begingroup$

Rosanswers logo

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


Originally posted by TFinleyosu on ROS Answers with karma: 385 on 2014-03-26

Post score: 4


Original comments

Comment by Wolf on 2014-03-26:
curiosity: Why would you want to implement that yourself? You can start rosbag like this also as node via launch file...

Comment by TFinleyosu on 2014-03-26:
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?

Comment by Wolf on 2014-03-26:
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...

Comment by TFinleyosu on 2014-03-27:
Thanks for the help Wolf

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

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.

Originally posted by timm with karma: 376 on 2014-03-27

This answer was ACCEPTED on the original site

Post score: 6


Original comments

Comment by TFinleyosu on 2014-03-27:
Great point. Thanks for the guidance. I will get to this soon and post my solution for reference.

$\endgroup$
0
$\begingroup$

Rosanswers logo

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();

  }

}

Originally posted by TFinleyosu with karma: 385 on 2014-03-31

This answer was NOT ACCEPTED on the original site

Post score: 2


Original comments

Comment by emacsd on 2015-02-27:
Thanks for sharing :)

Comment by Will Chamberlain on 2016-08-30:
In addition to excellent answer above, the rosbag API page links to some cookbook code snippets.

Comment by hannavaj on 2018-12-12:
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 ?

Comment by Wade on 2022-11-02:
Hello, could anyone suggest how can we add play rate of the rosbag in the above code as posted by @TFinleyosu ??

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.