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
00064
00065
00066 all_topics.pop_back();
00067
00068 if (ignoreAll) {
00069
00070
00071 continue;
00072 }
00073
00074
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
00090 throw;
00091 }
00092 if( msgBox.clickedButton() == buttonIgnoreAll)
00093 {
00094
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