00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef IGNORE_ROSRECORD_DEPRECATED
00036 #warning rosrecord/Player.h has been deprecated
00037 #endif
00038
00039 #ifndef ROSRECORDPLAYER_H
00040 #define ROSRECORDPLAYER_H
00041
00042 #include "rosrecord/AnyMsg.h"
00043 #include "rosrecord/MsgFunctor.h"
00044 #include "rosrecord/constants.h"
00045
00046 #include "rosbag/bag.h"
00047 #include "rosbag/view.h"
00048 #include "rosbag/time_translator.h"
00049
00050 #include "topic_tools/shape_shifter.h"
00051
00052 #include "std_msgs/String.h"
00053
00054 #include <boost/filesystem.hpp>
00055 #include <boost/foreach.hpp>
00056
00057 #define foreach BOOST_FOREACH
00058
00059 namespace ros
00060 {
00061 namespace record
00062 {
00063
00064 class Player
00065 {
00066 struct FilteredMsgFunctor
00067 {
00068 std::string topic_name;
00069 std::string md5sum;
00070 std::string datatype;
00071 bool inflate;
00072 AbstractMsgFunctor* f;
00073 };
00074
00075 public:
00076 ROS_DEPRECATED Player(double time_scale=1.0)
00077 {
00078 translator_.setTimeScale(time_scale);
00079 }
00080
00081 virtual ~Player() {
00082 foreach(FilteredMsgFunctor const& callback, callbacks_)
00083 delete callback.f;
00084
00085 close();
00086 }
00087
00088 std::string getVersionString() {
00089 std::stringstream ss;
00090 ss << bag_.getMajorVersion() << "." << bag_.getMinorVersion();
00091 return ss.str();
00092 }
00093
00094 bool isDone() { return iterator_ == view_.end(); }
00095
00096
00097 ros::Duration getFirstDuration() { return first_duration_; }
00098
00099 ros::Time getFirstTime() { return first_time_; }
00100
00101 void setTranslatedStartTime(const ros::Time& start_time)
00102 {
00103 translator_.setTranslatedStartTime(start_time);
00104 }
00105
00106 void setRealStartTime(const ros::Time& start_time)
00107 {
00108 translator_.setRealStartTime(start_time);
00109 }
00110
00111
00112 ros::Duration get_duration() { return duration_; }
00113
00114 void close() {
00115 iterator_ = view_.end();
00116
00117 bag_.close();
00118 }
00119
00120 bool open(std::string const& file_name, ros::Time start_time, bool try_future = false) {
00121 translator_.setTranslatedStartTime(start_time);
00122
00123 std::string ext = boost::filesystem::extension(file_name);
00124 if (ext != ".bag") {
00125 ROS_ERROR("File: '%s' does not have .bag extension",file_name.c_str());
00126 return false;
00127 }
00128
00129 try
00130 {
00131 bag_.open(file_name, rosbag::bagmode::Read);
00132 }
00133 catch (rosbag::BagException ex)
00134 {
00135 ROS_FATAL_STREAM("Failed to open file: " << file_name << " (" << ex.what() << ")");
00136 return false;
00137 }
00138
00139 view_.addQuery(bag_);
00140 iterator_ = view_.begin();
00141
00142 if (iterator_ != view_.end())
00143 {
00144 translator_.setRealStartTime(iterator_->getTime());
00145
00146 first_time_ = iterator_->getTime();
00147 first_duration_ = iterator_->getTime() - ros::Time(0,0);
00148 duration_ = iterator_->getTime() - first_time_;
00149 }
00150
00151 return true;
00152 }
00153
00154 template<class M>
00155 void addHandler(std::string topic_name, void(*fp)(std::string, ros::Message*, ros::Time, ros::Time, void*), void* ptr, bool inflate)
00156 {
00157 FilteredMsgFunctor fmf;
00158 fmf.topic_name = topic_name;
00159 fmf.md5sum = M::__s_getMD5Sum();
00160 fmf.datatype = M::__s_getDataType();
00161 fmf.inflate = inflate;
00162 fmf.f = new MsgFunctor<M>(fp, ptr, inflate);
00163
00164 callbacks_.push_back(fmf);
00165 }
00166
00167
00168 template<class M>
00169 void addHandler(std::string topic_name, void(*fp)(std::string, M*, ros::Time, ros::Time, void*), void* ptr)
00170 {
00171 FilteredMsgFunctor fmf;
00172 fmf.topic_name = topic_name;
00173 fmf.md5sum = M::__s_getMD5Sum();
00174 fmf.datatype = M::__s_getDataType();
00175 fmf.inflate = true;
00176 fmf.f = new MsgFunctor<M>(fp, ptr);
00177
00178 callbacks_.push_back(fmf);
00179 }
00180
00181 template<class M, class T>
00182 void addHandler(std::string topic_name, void(T::*fp)(std::string, ros::Message*, ros::Time, ros::Time, void*), T* obj, void* ptr, bool inflate)
00183 {
00184 FilteredMsgFunctor fmf;
00185 fmf.topic_name = topic_name;
00186 fmf.md5sum = M::__s_getMD5Sum();
00187 fmf.datatype = M::__s_getDataType();
00188 fmf.inflate = inflate;
00189 fmf.f = new MsgFunctor<M, T>(obj, fp, ptr, inflate);
00190
00191 callbacks_.push_back(fmf);
00192 }
00193
00194
00195 template<class M, class T>
00196 void addHandler(std::string topic_name, void(T::*fp)(std::string, M*, ros::Time, ros::Time, void*), T* obj, void* ptr)
00197 {
00198 FilteredMsgFunctor fmf;
00199 fmf.topic_name = topic_name;
00200 fmf.md5sum = M::__s_getMD5Sum();
00201 fmf.datatype = M::__s_getDataType();
00202 fmf.inflate = true;
00203 fmf.f = new MsgFunctor<M, T>(obj, fp, ptr);
00204
00205 callbacks_.push_back(fmf);
00206 }
00207
00208 ros::Time get_next_msg_time() {
00209 if (isDone())
00210 return ros::Time();
00211
00212 return (*iterator_).getTime();
00213 }
00214
00215 bool nextMsg() {
00216 if (iterator_ == view_.end())
00217 return false;
00218
00219 rosbag::MessageInstance msg = (*iterator_);
00220
00221 std::string const& topic = msg.getTopic();
00222 std::string const& md5sum = msg.getMD5Sum();
00223 std::string const& datatype = msg.getDataType();
00224
00225 duration_ = msg.getTime() - first_time_;
00226
00227
00228 std::vector<FilteredMsgFunctor> callbacks;
00229 foreach(FilteredMsgFunctor fmf, callbacks_)
00230 {
00231 if (topic != fmf.topic_name && fmf.topic_name != std::string("*"))
00232 continue;
00233 if (fmf.md5sum != md5sum && fmf.md5sum != std::string("*"))
00234 continue;
00235 if (fmf.datatype != datatype && fmf.datatype != std::string("*") && datatype != std::string("*"))
00236 continue;
00237
00238 callbacks.push_back(fmf);
00239 }
00240
00241 if (callbacks.size() > 0) {
00242 boost::shared_ptr<topic_tools::ShapeShifter const> ss = msg.instantiate<topic_tools::ShapeShifter>();
00243
00244 ros::Time const& time = msg.getTime();
00245 ros::Time const& translated_time = translator_.translate(time);
00246
00247 foreach(FilteredMsgFunctor fmf, callbacks)
00248 fmf.f->call(topic, (ros::Message*) ss.get(), translated_time, time);
00249 }
00250
00251 iterator_++;
00252
00253 return true;
00254 }
00255
00256 void shiftTime(ros::Duration shift) {
00257 translator_.shift(shift);
00258 }
00259
00260 private:
00261
00262
00263
00264
00265 rosbag::TimeTranslator translator_;
00266 ros::Time first_time_;
00267 ros::Duration first_duration_;
00268 ros::Duration duration_;
00269
00270 rosbag::Bag bag_;
00271 rosbag::View view_;
00272 rosbag::View::const_iterator iterator_;
00273
00274 std::vector<FilteredMsgFunctor> callbacks_;
00275 };
00276
00277 class MultiPlayer
00278 {
00279 public:
00280 MultiPlayer() { }
00281
00282 ~MultiPlayer() {
00283 foreach(Player* player, players_)
00284 delete player;
00285 }
00286
00287 ros::Duration getDuration()
00288 {
00289 ros::Duration d(0.0);
00290 foreach(Player* player, players_) {
00291 ros::Duration dd = player->get_duration();
00292 if (dd > d)
00293 d = dd;
00294 }
00295 return d;
00296 }
00297
00298 ros::Time getFirstTime() { return first_time_; }
00299
00300 bool open(std::vector<std::string> file_names, ros::Time start, double time_scale = 1, bool try_future = false)
00301 {
00302 ros::Duration first_duration;
00303
00304 foreach(std::string file_name, file_names) {
00305 Player* l = new Player(time_scale);
00306 if (l->open(file_name, ros::Time(), try_future)) {
00307 players_.push_back(l);
00308
00309
00310 if (first_duration == ros::Duration() || l->getFirstDuration() < first_duration)
00311 first_duration = l->getFirstDuration();
00312
00313 if (first_time_ == ros::Time() || l->getFirstTime() < first_time_)
00314 first_time_ = l->getFirstTime();
00315 }
00316 else {
00317 delete l;
00318 return false;
00319 }
00320 }
00321
00322 foreach(Player* player, players_)
00323 {
00324 player->setRealStartTime(first_time_);
00325 player->setTranslatedStartTime(start);
00326 }
00327
00328 return true;
00329 }
00330
00331 void shiftTime(ros::Duration shift)
00332 {
00333 for (std::vector<Player*>::iterator player_it = players_.begin(); player_it != players_.end(); player_it++)
00334 (*player_it)->shiftTime(shift);
00335 }
00336
00337 template<class M>
00338 void addHandler(std::string topic_name, void(*fp)(std::string, ros::Message*, ros::Time, ros::Time, void*), void* ptr, bool inflate)
00339 {
00340 for (std::vector<Player*>::iterator player_it = players_.begin(); player_it != players_.end(); player_it++)
00341 (*player_it)->addHandler<M>(topic_name, fp, ptr, inflate);
00342 }
00343
00344 template<class M>
00345 void addHandler(std::string topic_name, void(*fp)(std::string, M*, ros::Time, ros::Time, void*), void* ptr)
00346 {
00347 for (std::vector<Player*>::iterator player_it = players_.begin(); player_it != players_.end(); player_it++)
00348 (*player_it)->addHandler<M>(topic_name, fp, ptr);
00349 }
00350
00351 template<class M, class T>
00352 void addHandler(std::string topic_name, void(T::*fp)(std::string, ros::Message*, ros::Time, ros::Time, void*), T* obj, void* ptr, bool inflate)
00353 {
00354 for (std::vector<Player*>::iterator player_it = players_.begin(); player_it != players_.end(); player_it++)
00355 (*player_it)->addHandler<M>(topic_name, fp, obj, ptr, inflate);
00356 }
00357
00358 template<class M, class T>
00359 void addHandler(std::string topic_name, void(T::*fp)(std::string, M*, ros::Time, ros::Time, void*), T* obj, void* ptr)
00360 {
00361 for (std::vector<Player*>::iterator player_it = players_.begin(); player_it != players_.end(); player_it++)
00362 (*player_it)->addHandler<M>(topic_name, fp, obj, ptr);
00363 }
00364
00365 bool nextMsg()
00366 {
00367 Player* next_player = NULL;
00368
00369 bool first = true;
00370 ros::Time min_t = ros::TIME_MAX;
00371
00372 bool remaining = false;
00373
00374 foreach(Player* player, players_) {
00375 if (player->isDone())
00376 continue;
00377
00378 remaining = true;
00379 ros::Time t = player->get_next_msg_time();
00380 if (first || t < min_t) {
00381 first = false;
00382 next_player = player;
00383 min_t = player->get_next_msg_time();
00384 }
00385 }
00386 if (next_player)
00387 next_player->nextMsg();
00388
00389 return remaining;
00390 }
00391
00392 private:
00393 std::vector<Player*> players_;
00394 ros::Time first_time_;
00395 };
00396
00397 }
00398
00399 }
00400
00401 #endif