dataload_ros.cpp
Go to the documentation of this file.
00001 #include "dataload_ros.h"
00002 #include <QTextStream>
00003 #include <QFile>
00004 #include <QMessageBox>
00005 #include <QPushButton>
00006 #include <QDebug>
00007 #include <QApplication>
00008 #include <QProgressDialog>
00009 #include <QFileInfo>
00010 #include <QProcess>
00011 #include <rosbag/view.h>
00012 #include <QSettings>
00013 #include <QElapsedTimer>
00014 
00015 #include "../dialog_select_ros_topics.h"
00016 #include "../shape_shifter_factory.hpp"
00017 #include "../rule_editing.h"
00018 #include "../dialog_with_itemlist.h"
00019 
00020 DataLoadROS::DataLoadROS()
00021 {
00022     _extensions.push_back( "bag");
00023     loadDefaultSettings();
00024 }
00025 
00026 void StrCat(const std::string& a, const std::string& b,  std::string& out)
00027 {
00028     out.clear();
00029     out.reserve(a.size() + b.size());
00030     out.assign(a);
00031     out.append(b);
00032 }
00033 
00034 const std::vector<const char*> &DataLoadROS::compatibleFileExtensions() const
00035 {
00036     return _extensions;
00037 }
00038 
00039 std::vector<std::pair<QString,QString>> DataLoadROS::getAndRegisterAllTopics()
00040 {
00041     std::vector<std::pair<QString,QString>> all_topics;
00042     rosbag::View bag_view ( *_bag, ros::TIME_MIN, ros::TIME_MAX, true );
00043 
00044     RosIntrospectionFactory::reset();
00045 
00046     bool ignoreAll = false;
00047 
00048     for(auto& conn: bag_view.getConnections() )
00049     {
00050         const auto&  topic      =  conn->topic;
00051         const auto&  md5sum     =  conn->md5sum;
00052         const auto&  datatype   =  conn->datatype;
00053         const auto&  definition =  conn->msg_def;
00054 
00055         all_topics.push_back( std::make_pair(QString( topic.c_str()), QString( datatype.c_str()) ) );
00056         try {
00057             _ros_parser.registerSchema(
00058                     topic, md5sum, RosIntrospection::ROSType(datatype), definition);
00059             RosIntrospectionFactory::registerMessage(topic, md5sum, datatype, definition);
00060         }
00061         catch(std::exception &ex)
00062         {
00063             // there was a problem with this topic
00064             // a real life problem example can be found here:
00065             // https://github.com/rosjava/rosjava_bootstrap/issues/16
00066             all_topics.pop_back();
00067 
00068             if (ignoreAll) {
00069                 // this is not the first error with this load and the
00070                 // user has accepted to ignore all errors
00071                 continue;
00072             }
00073 
00074             // prompt user to abort or continue
00075             QMessageBox msgBox(nullptr);
00076             msgBox.setWindowTitle("ROS bag error");
00077             msgBox.setText(QString("Topic ") +
00078                            QString(topic.c_str()) +
00079                            QString(": ") +
00080                            QString(ex.what()));
00081 
00082             QPushButton* buttonCancel = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
00083             QPushButton* buttonIgnore = msgBox.addButton(tr("Ignore"), QMessageBox::YesRole);
00084             QPushButton* buttonIgnoreAll = msgBox.addButton(tr("Ignore all"), QMessageBox::AcceptRole);
00085             msgBox.setDefaultButton(buttonIgnoreAll);
00086             msgBox.exec();
00087             if( msgBox.clickedButton() == buttonCancel)
00088             {
00089                 // abort the file loading
00090                 throw;
00091             }
00092             if( msgBox.clickedButton() == buttonIgnoreAll)
00093             {
00094                 // accept this and all future errors for this load
00095                 ignoreAll = true;
00096             }
00097         }
00098     }
00099     return all_topics;
00100 }
00101 
00102 
00103 bool DataLoadROS::readDataFromFile(FileLoadInfo* info, PlotDataMapRef& plot_map)
00104 {
00105     if( _bag ) _bag->close();
00106 
00107     _bag = std::make_shared<rosbag::Bag>();
00108     _ros_parser.clear();
00109 
00110     try{
00111         _bag->open( info->filename.toStdString(), rosbag::bagmode::Read );
00112     }
00113     catch( rosbag::BagException&  ex)
00114     {
00115         QMessageBox::warning(nullptr, tr("Error"),
00116                              QString("rosbag::open thrown an exception:\n")+
00117                              QString(ex.what()) );
00118         return false;
00119     }
00120 
00121     auto all_topics = getAndRegisterAllTopics();
00122 
00123     //----------------------------------
00124 
00125     if( info->plugin_config.hasChildNodes() )
00126     {
00127         xmlLoadState( info->plugin_config.firstChildElement() );
00128     }
00129 
00130     if( ! info->selected_datasources.empty() )
00131     {
00132             _config.selected_topics =   info->selected_datasources;
00133     }
00134     else{
00135         DialogSelectRosTopics* dialog = new DialogSelectRosTopics( all_topics, _config );
00136 
00137         if( dialog->exec() != static_cast<int>(QDialog::Accepted) )
00138         {
00139             return false;
00140         }
00141         _config = dialog->getResult();
00142     }
00143 
00144     saveDefaultSettings();
00145 
00146     _ros_parser.setUseHeaderStamp( _config.use_header_stamp );
00147     _ros_parser.setMaxArrayPolicy( _config.max_array_size, _config.discard_large_arrays );
00148 
00149     if( _config.use_renaming_rules )
00150     {
00151         _ros_parser.addRules( RuleEditing::getRenamingRules() );
00152     }
00153 
00154     //-----------------------------------
00155     std::set<std::string> topic_selected;
00156     for(const auto& topic: _config.selected_topics)
00157     {
00158         topic_selected.insert( topic.toStdString() );
00159     }
00160 
00161     QProgressDialog progress_dialog;
00162     progress_dialog.setLabelText("Loading... please wait");
00163     progress_dialog.setWindowModality( Qt::ApplicationModal );
00164 
00165     rosbag::View bag_view ( *_bag );
00166 
00167     progress_dialog.setRange(0, bag_view.size()-1);
00168     progress_dialog.show();
00169 
00170     std::vector<uint8_t> buffer;
00171 
00172     int msg_count = 0;
00173 
00174     QElapsedTimer timer;
00175     timer.start();
00176 
00177 
00178     PlotDataAny& plot_consecutive = plot_map.addUserDefined( "__consecutive_message_instances__" )->second;
00179 
00180     for(const rosbag::MessageInstance& msg_instance: bag_view)
00181     {
00182 
00183         const std::string& topic_name  = msg_instance.getTopic();
00184         double msg_time = msg_instance.getTime().toSec();
00185         auto data_point = PlotDataAny::Point(msg_time, nonstd::any(msg_instance) );
00186         plot_consecutive.pushBack( data_point );
00187 
00188         const std::string* key_ptr = &topic_name ;
00189 
00190         auto plot_pair = plot_map.user_defined.find( *key_ptr );
00191         if( plot_pair == plot_map.user_defined.end() )
00192         {
00193             plot_pair = plot_map.addUserDefined( *key_ptr );
00194         }
00195         PlotDataAny& plot_raw = plot_pair->second;
00196         plot_raw.pushBack( data_point );
00197         //------------------------------------------
00198         if( msg_count++ %100 == 0)
00199         {
00200             progress_dialog.setValue( msg_count );
00201             QApplication::processEvents();
00202 
00203             if( progress_dialog.wasCanceled() ) {
00204                 return false;
00205             }
00206         }
00207         //------------------------------------------
00208         if( topic_selected.find( topic_name ) == topic_selected.end() )
00209         {
00210             continue;
00211         }
00212 
00213         const size_t msg_size  = msg_instance.size();
00214         buffer.resize(msg_size);
00215 
00216         ros::serialization::OStream stream(buffer.data(), buffer.size());
00217         msg_instance.write(stream);
00218         MessageRef buffer_view( buffer );
00219         _ros_parser.pushMessageRef( topic_name, buffer_view, msg_time );
00220     }
00221 
00222     _ros_parser.extractData(plot_map, "");
00223 
00224     qDebug() << "The loading operation took" << timer.elapsed() << "milliseconds";
00225 
00226     info->selected_datasources = _config.selected_topics;
00227     return true;
00228 }
00229 
00230 DataLoadROS::~DataLoadROS()
00231 {
00232 
00233 }
00234 
00235 bool DataLoadROS::xmlSaveState(QDomDocument &doc, QDomElement &plugin_elem) const
00236 {
00237     QDomElement stamp_elem = doc.createElement("use_header_stamp");
00238     stamp_elem.setAttribute("value", _config.use_header_stamp ? "true" : "false");
00239     plugin_elem.appendChild( stamp_elem );
00240 
00241     QDomElement rename_elem = doc.createElement("use_renaming_rules");
00242     rename_elem.setAttribute("value", _config.use_renaming_rules ? "true" : "false");
00243     plugin_elem.appendChild( rename_elem );
00244 
00245     QDomElement discard_elem = doc.createElement("discard_large_arrays");
00246     discard_elem.setAttribute("value", _config.discard_large_arrays ? "true" : "false");
00247     plugin_elem.appendChild( discard_elem );
00248 
00249     QDomElement max_elem = doc.createElement("max_array_size");
00250     max_elem.setAttribute("value", QString::number(_config.max_array_size));
00251     plugin_elem.appendChild( max_elem );
00252 
00253     return true;
00254 }
00255 
00256 bool DataLoadROS::xmlLoadState(const QDomElement &parent_element)
00257 {
00258     QDomElement stamp_elem = parent_element.firstChildElement( "use_header_stamp" );
00259     _config.use_header_stamp = ( stamp_elem.attribute("value") == "true");
00260 
00261     QDomElement rename_elem = parent_element.firstChildElement( "use_renaming_rules" );
00262     _config.use_renaming_rules = ( rename_elem.attribute("value") == "true");
00263 
00264     QDomElement discard_elem = parent_element.firstChildElement( "discard_large_arrays" );
00265     _config.discard_large_arrays = ( discard_elem.attribute("value") == "true");
00266 
00267     QDomElement max_elem = parent_element.firstChildElement( "max_array_size" );
00268     _config.max_array_size = max_elem.attribute("value").toInt();
00269 
00270     return true;
00271 }
00272 
00273 void DataLoadROS::saveDefaultSettings()
00274 {
00275     QSettings settings;
00276 
00277     settings.setValue("DataLoadROS/default_topics", _config.selected_topics);
00278     settings.setValue("DataLoadROS/use_renaming", _config.use_renaming_rules);
00279     settings.setValue("DataLoadROS/use_header_stamp", _config.use_header_stamp);
00280     settings.setValue("DataLoadROS/max_array_size", (int)_config.max_array_size);
00281     settings.setValue("DataLoadROS/discard_large_arrays", _config.discard_large_arrays);
00282 }
00283 
00284 
00285 void DataLoadROS::loadDefaultSettings()
00286 {
00287     QSettings settings;
00288 
00289     _config.selected_topics      = settings.value("DataLoadROS/default_topics", false ).toStringList();
00290     _config.use_header_stamp     = settings.value("DataLoadROS/use_header_stamp", false ).toBool();
00291     _config.use_renaming_rules   = settings.value("DataLoadROS/use_renaming", true ).toBool();
00292     _config.max_array_size       = settings.value("DataLoadROS/max_array_size", 100 ).toInt();
00293     _config.discard_large_arrays = settings.value("DataLoadROS/discard_large_arrays", true ).toBool();
00294 }
00295 


plotjuggler
Author(s): Davide Faconti
autogenerated on Wed Jul 3 2019 19:28:04