BagReader.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  * Copyright (C) 2015 by Ralf Kaestner                                        *
00003  * ralf.kaestner@gmail.com                                                    *
00004  *                                                                            *
00005  * This program is free software; you can redistribute it and/or modify       *
00006  * it under the terms of the Lesser GNU General Public License as published by*
00007  * the Free Software Foundation; either version 3 of the License, or          *
00008  * (at your option) any later version.                                        *
00009  *                                                                            *
00010  * This program is distributed in the hope that it will be useful,            *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               *
00013  * Lesser GNU General Public License for more details.                        *
00014  *                                                                            *
00015  * You should have received a copy of the Lesser GNU General Public License   *
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.       *
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 /* Constructors and Destructor                                               */
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 /* Accessors                                                                 */
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 /* Methods                                                                   */
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 /* Slots                                                                     */
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 }


rqt_multiplot
Author(s): Ralf Kaestner
autogenerated on Thu Jun 6 2019 21:49:10