Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <QApplication>
00020 #include <QMutexLocker>
00021
00022 #include <rosbag/bag.h>
00023 #include <ros/console.h>
00024 #include <rosbag/view.h>
00025
00026 #include <rqt_multiplot/ProgressChangeEvent.h>
00027
00028 #include "rqt_multiplot/BagReader.h"
00029
00030 namespace rqt_multiplot {
00031
00032
00033
00034
00035
00036 BagReader::BagReader(QObject* parent) :
00037 MessageBroker(parent),
00038 impl_(this) {
00039 connect(&impl_, SIGNAL(started()), this, SLOT(threadStarted()));
00040 connect(&impl_, SIGNAL(finished()), this, SLOT(threadFinished()));
00041 }
00042
00043 BagReader::~BagReader() {
00044 impl_.quit();
00045 impl_.wait();
00046 }
00047
00048 BagReader::Impl::Impl(QObject* parent) :
00049 QThread(parent) {
00050 }
00051
00052 BagReader::Impl::~Impl() {
00053 terminate();
00054 wait();
00055 }
00056
00057
00058
00059
00060
00061 QString BagReader::getFileName() const {
00062 return impl_.fileName_;
00063 }
00064
00065 QString BagReader::getError() const {
00066 return impl_.error_;
00067 }
00068
00069 bool BagReader::isReading() const {
00070 return impl_.isRunning();
00071 }
00072
00073
00074
00075
00076
00077 void BagReader::read(const QString& fileName) {
00078 impl_.wait();
00079
00080 impl_.fileName_ = fileName;
00081 impl_.error_.clear();
00082
00083 impl_.start();
00084 }
00085
00086 void BagReader::wait() {
00087 impl_.wait();
00088 }
00089
00090 bool BagReader::subscribe(const QString& topic, QObject* receiver, const
00091 char* method, const PropertyMap& properties, Qt::ConnectionType type) {
00092 QMutexLocker lock(&impl_.mutex_);
00093
00094 QMap<QString, BagQuery*>::iterator it = impl_.queries_.find(topic);
00095
00096 if (it == impl_.queries_.end()) {
00097 it = impl_.queries_.insert(topic, new BagQuery(this));
00098
00099 connect(it.value(), SIGNAL(aboutToBeDestroyed()), this,
00100 SLOT(queryAboutToBeDestroyed()));
00101 }
00102
00103 return receiver->connect(it.value(), SIGNAL(messageRead(const
00104 QString&, const Message&)), method, type);
00105 }
00106
00107 bool BagReader::unsubscribe(const QString& topic, QObject* receiver,
00108 const char* method) {
00109 QMutexLocker lock(&impl_.mutex_);
00110
00111 QMap<QString, BagQuery*>::iterator it = impl_.queries_.find(topic);
00112
00113 if (it != impl_.queries_.end()) {
00114 return it.value()->disconnect(SIGNAL(messageRead(const QString&,
00115 const Message&)), receiver, method);
00116 }
00117 else
00118 return false;
00119 }
00120
00121 bool BagReader::event(QEvent* event) {
00122 if (event->type() == ProgressChangeEvent::Type) {
00123 ProgressChangeEvent* progressChangeEvent = static_cast<
00124 ProgressChangeEvent*>(event);
00125
00126 emit readingProgressChanged(progressChangeEvent->getProgress());
00127
00128 return true;
00129 }
00130
00131 return QObject::event(event);
00132 }
00133
00134 void BagReader::Impl::run() {
00135 if (queries_.isEmpty())
00136 return;
00137
00138 try {
00139 rosbag::Bag bag;
00140
00141 bag.open(fileName_.toStdString(), rosbag::bagmode::Read);
00142
00143 std::vector<std::string> queriedTopics;
00144 queriedTopics.reserve(queries_.count());
00145
00146 for (QMap<QString, BagQuery*>::const_iterator jt = queries_.begin();
00147 jt != queries_.end(); ++jt)
00148 queriedTopics.push_back(jt.key().toStdString());
00149
00150 rosbag::View view(bag, rosbag::TopicQuery(queriedTopics));
00151
00152 for (rosbag::View::iterator it = view.begin(); it != view.end();
00153 ++it) {
00154 mutex_.lock();
00155
00156 QMap<QString, BagQuery*>::const_iterator jt = queries_.find(
00157 QString::fromStdString(it->getTopic()));
00158
00159 if (jt != queries_.end())
00160 jt.value()->callback(*it);
00161
00162 mutex_.unlock();
00163
00164 double progress = (it->getTime()-view.getBeginTime()).toSec()/
00165 (view.getEndTime()-view.getBeginTime()).toSec();
00166
00167 ProgressChangeEvent* progressChangeEvent = new
00168 ProgressChangeEvent(progress);
00169
00170 QApplication::postEvent(parent(), progressChangeEvent);
00171 }
00172 }
00173 catch (const ros::Exception& exception) {
00174 error_ = QString::fromStdString(exception.what());
00175 }
00176 }
00177
00178
00179
00180
00181
00182 void BagReader::threadStarted() {
00183 emit readingStarted();
00184 }
00185
00186 void BagReader::threadFinished() {
00187 if (impl_.error_.isEmpty()) {
00188 ROS_INFO_STREAM("Read bag from [file://" <<
00189 impl_.fileName_.toStdString() << "]");
00190
00191 emit readingFinished();
00192 }
00193 else {
00194 ROS_ERROR_STREAM("Failed to read bag from [file://" <<
00195 impl_.fileName_.toStdString() << "]: " <<
00196 impl_.error_.toStdString());
00197
00198 emit readingFailed(impl_.error_);
00199 }
00200 }
00201
00202 void BagReader::queryAboutToBeDestroyed() {
00203 for (QMap<QString, BagQuery*>::iterator it = impl_.queries_.begin();
00204 it != impl_.queries_.end(); ++it) {
00205 if (it.value() == static_cast<BagQuery*>(sender())) {
00206 impl_.queries_.erase(it);
00207 break;
00208 }
00209 }
00210 }
00211
00212 }