Go to the documentation of this file.00001
00059 #include <boost/program_options.hpp>
00060
00061 #include <rosbag/bag.h>
00062 #include <rosbag/view.h>
00063 #include <tf/transform_broadcaster.h>
00064
00065 #include <cob_3d_mapping_tools/keyboard_console_listener.hpp>
00066
00067 namespace cob_3d_mapping_tools
00068 {
00069 struct BAG_MODE
00070 {
00071 enum modes
00072 {
00073 BACKWARD, FORWARD
00074 };
00075 };
00076
00077 template<typename MsgT>
00078 class bag_delayer
00079 {
00080 private:
00081 typedef KeyboardConsoleListener KCL;
00082
00083 public:
00084 bag_delayer()
00085 : mode(BAG_MODE::FORWARD)
00086 , b_run(false)
00087 , p_bag(NULL)
00088 , p_view(NULL)
00089 , n_msg(0)
00090 {
00091 keys[0] = KCL::KEYS::F;
00092 keys[1] = KCL::KEYS::B;
00093 keys[2] = KCL::KEYS::SPACE;
00094 keys_size = 3;
00095 }
00096
00097 ~bag_delayer()
00098 { deinit(); }
00099
00100 bool init(int argc, char* argv[]);
00101 void deinit();
00102 void run();
00103
00104 private:
00105 void interpret_input(char c_in);
00106
00107
00108 BAG_MODE::modes mode;
00109 bool b_run;
00110 std::string topic_;
00111
00112 rosbag::Bag *p_bag;
00113 rosbag::View *p_view;
00114 tf::TransformBroadcaster *tf_broadcaster;
00115 std::list<rosbag::View::iterator> timeline;
00116
00117 int n_msg;
00118 char keys[3];
00119 int keys_size;
00120 };
00121
00122 template <typename MsgT> bool
00123 bag_delayer<MsgT>::init(int argc, char* argv[])
00124 {
00125 std::string bag_file;
00126 unsigned int delay;
00127
00128 using namespace boost::program_options;
00129 options_description options("Options");
00130 options.add_options()
00131 ("help", "produce help message")
00132 ("in", value<std::string>(&bag_file), "input pcd file")
00133 ("delay,d", value<unsigned int>(&delay)->default_value(1), "delay * 0.1 sec")
00134 ("topic,t", value<std::string>(&topic_)->default_value("/registration/pc_aligned"), "message topic to delay")
00135 ;
00136
00137 positional_options_description p_opt;
00138 p_opt.add("in", 1);
00139 variables_map vm;
00140 store(command_line_parser(argc, argv).options(options).positional(p_opt).run(), vm);
00141 notify(vm);
00142
00143 if (vm.count("help") || argc == 1)
00144 {
00145 std::cout << "Press Key:" << std::endl;
00146 std::cout << "[f] to step forward one message" << std::endl;
00147 std::cout << "[b] to step backward one message" << std::endl;
00148 std::cout << "[space] to pause/unpause bagfile iteration in previously used direction" << std::endl;
00149 std::cout << options << std::endl;
00150 return false;
00151 }
00152 if (bag_file == "")
00153 {
00154 std::cout << "no input file defined " << std::endl << options << std::endl;
00155 return false;
00156 }
00157
00158 p_bag = new rosbag::Bag();
00159 p_view = new rosbag::View();
00160 tf_broadcaster = new tf::TransformBroadcaster();
00161
00162 try { p_bag->open(bag_file, rosbag::bagmode::Read); }
00163 catch (rosbag::BagException) { std::cerr << "Error opening file " << bag_file << std::endl; return false; }
00164 p_view->addQuery(*p_bag, rosbag::TopicQuery(topic_));
00165 p_view->addQuery(*p_bag, rosbag::TypeQuery("tf/tfMessage"));
00166
00167 rosbag::View::iterator vit = p_view->begin();
00168 while(vit!=p_view->end()) { timeline.push_back(vit); ++vit; }
00169
00170 KCL::get().init(delay);
00171 return true;
00172 }
00173
00174 template <typename MsgT> void
00175 bag_delayer<MsgT>::deinit()
00176 {
00177 KCL::get().reset();
00178 if(p_bag) { p_bag->close(); delete p_bag; }
00179 delete p_view;
00180 delete tf_broadcaster;
00181 }
00182
00183 template <typename MsgT> void
00184 bag_delayer<MsgT>::run()
00185 {
00186 typename MsgT::ConstPtr last_msg;
00187 tf::tfMessage::ConstPtr last_tf;
00188 std::list<rosbag::View::iterator>::iterator tl_it = timeline.begin();
00189 ros::NodeHandle nh;
00190 ros::Publisher pub = nh.advertise<MsgT>(this->topic_,1);
00191 while(ros::ok())
00192 {
00193 if(!this->b_run) { interpret_input(KCL::get().waitForIt(keys, keys_size)); }
00194 else { interpret_input(KCL::get().spinOnce()); }
00195
00196 while(last_msg==NULL)
00197 {
00198 if(tl_it == timeline.end()) { deinit(); exit(0); }
00199
00200 last_tf = (*tl_it)->instantiate<tf::tfMessage>();
00201 if (last_tf != NULL)
00202 {
00203 tf_broadcaster->sendTransform(last_tf->transforms);
00204 ros::spinOnce();
00205 }
00206 last_msg = (*tl_it)->instantiate<MsgT>();
00207 if(mode==BAG_MODE::FORWARD) { ++tl_it; }
00208 else if(mode==BAG_MODE::BACKWARD && tl_it != timeline.begin()) { --tl_it; }
00209 else { deinit(); exit(0); }
00210 }
00211 if (mode==BAG_MODE::FORWARD) std::cout << "Msg no."<<++n_msg<<" : " << last_msg->header.stamp << std::endl;
00212 else if (mode==BAG_MODE::BACKWARD) std::cout << "Msg no."<<--n_msg<<" : " << last_msg->header.stamp << std::endl;
00213 pub.publish(last_msg);
00214 last_msg.reset();
00215 last_tf.reset();
00216 }
00217 }
00218
00219 template <typename MsgT> void
00220 bag_delayer<MsgT>::interpret_input(char c_in)
00221 {
00222
00223 switch (c_in)
00224 {
00225 case KCL::KEYS::SPACE:
00226
00227 this->b_run = !this->b_run;
00228 break;
00229 case KCL::KEYS::B:
00230 this->mode = BAG_MODE::BACKWARD;
00231 break;
00232 case KCL::KEYS::F:
00233 this->mode = BAG_MODE::FORWARD;
00234 break;
00235 }
00236 }
00237 }