dataload_ros.cpp
Go to the documentation of this file.
1 #include "dataload_ros.h"
2 #include <QTextStream>
3 #include <QFile>
4 #include <QMessageBox>
5 #include <QPushButton>
6 #include <QDebug>
7 #include <QApplication>
8 #include <QProgressDialog>
9 #include <QFileInfo>
10 #include <QProcess>
11 #include <rosbag/view.h>
12 #include <QSettings>
13 #include <QElapsedTimer>
14 
15 #include "../dialog_select_ros_topics.h"
16 #include "../shape_shifter_factory.hpp"
17 #include "../rule_editing.h"
18 #include "../dialog_with_itemlist.h"
19 
21 {
22  _extensions.push_back( "bag");
24 }
25 
26 void StrCat(const std::string& a, const std::string& b, std::string& out)
27 {
28  out.clear();
29  out.reserve(a.size() + b.size());
30  out.assign(a);
31  out.append(b);
32 }
33 
34 const std::vector<const char*> &DataLoadROS::compatibleFileExtensions() const
35 {
36  return _extensions;
37 }
38 
39 std::vector<std::pair<QString,QString>> DataLoadROS::getAndRegisterAllTopics()
40 {
41  std::vector<std::pair<QString,QString>> all_topics;
42  rosbag::View bag_view ( *_bag, ros::TIME_MIN, ros::TIME_MAX, true );
43 
45 
46  bool ignoreAll = false;
47 
48  for(auto& conn: bag_view.getConnections() )
49  {
50  const auto& topic = conn->topic;
51  const auto& md5sum = conn->md5sum;
52  const auto& datatype = conn->datatype;
53  const auto& definition = conn->msg_def;
54 
55  all_topics.push_back( std::make_pair(QString( topic.c_str()), QString( datatype.c_str()) ) );
56  try {
58  topic, md5sum, RosIntrospection::ROSType(datatype), definition);
59  RosIntrospectionFactory::registerMessage(topic, md5sum, datatype, definition);
60  }
61  catch(std::exception &ex)
62  {
63  // there was a problem with this topic
64  // a real life problem example can be found here:
65  // https://github.com/rosjava/rosjava_bootstrap/issues/16
66  all_topics.pop_back();
67 
68  if (ignoreAll) {
69  // this is not the first error with this load and the
70  // user has accepted to ignore all errors
71  continue;
72  }
73 
74  // prompt user to abort or continue
75  QMessageBox msgBox(nullptr);
76  msgBox.setWindowTitle("ROS bag error");
77  msgBox.setText(QString("Topic ") +
78  QString(topic.c_str()) +
79  QString(": ") +
80  QString(ex.what()));
81 
82  QPushButton* buttonCancel = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
83  QPushButton* buttonIgnore = msgBox.addButton(tr("Ignore"), QMessageBox::YesRole);
84  QPushButton* buttonIgnoreAll = msgBox.addButton(tr("Ignore all"), QMessageBox::AcceptRole);
85  msgBox.setDefaultButton(buttonIgnoreAll);
86  msgBox.exec();
87  if( msgBox.clickedButton() == buttonCancel)
88  {
89  // abort the file loading
90  throw;
91  }
92  if( msgBox.clickedButton() == buttonIgnoreAll)
93  {
94  // accept this and all future errors for this load
95  ignoreAll = true;
96  }
97  }
98  }
99  return all_topics;
100 }
101 
102 
104 {
105  if( _bag ) _bag->close();
106 
107  _bag = std::make_shared<rosbag::Bag>();
108  _ros_parser.clear();
109 
110  try{
111  _bag->open( info->filename.toStdString(), rosbag::bagmode::Read );
112  }
113  catch( rosbag::BagException& ex)
114  {
115  QMessageBox::warning(nullptr, tr("Error"),
116  QString("rosbag::open thrown an exception:\n")+
117  QString(ex.what()) );
118  return false;
119  }
120 
121  auto all_topics = getAndRegisterAllTopics();
122 
123  //----------------------------------
124 
125  if( info->plugin_config.hasChildNodes() )
126  {
127  xmlLoadState( info->plugin_config.firstChildElement() );
128  }
129 
130  if( ! info->selected_datasources.empty() )
131  {
133  }
134  else{
135  DialogSelectRosTopics* dialog = new DialogSelectRosTopics( all_topics, _config );
136 
137  if( dialog->exec() != static_cast<int>(QDialog::Accepted) )
138  {
139  return false;
140  }
141  _config = dialog->getResult();
142  }
143 
145 
148 
150  {
152  }
153 
154  //-----------------------------------
155  std::set<std::string> topic_selected;
156  for(const auto& topic: _config.selected_topics)
157  {
158  topic_selected.insert( topic.toStdString() );
159  }
160 
161  QProgressDialog progress_dialog;
162  progress_dialog.setLabelText("Loading... please wait");
163  progress_dialog.setWindowModality( Qt::ApplicationModal );
164 
165  rosbag::View bag_view ( *_bag );
166 
167  progress_dialog.setRange(0, bag_view.size()-1);
168  progress_dialog.show();
169 
170  std::vector<uint8_t> buffer;
171 
172  int msg_count = 0;
173 
174  QElapsedTimer timer;
175  timer.start();
176 
177 
178  PlotDataAny& plot_consecutive = plot_map.addUserDefined( "__consecutive_message_instances__" )->second;
179 
180  for(const rosbag::MessageInstance& msg_instance: bag_view)
181  {
182 
183  const std::string& topic_name = msg_instance.getTopic();
184  double msg_time = msg_instance.getTime().toSec();
185  auto data_point = PlotDataAny::Point(msg_time, nonstd::any(msg_instance) );
186  plot_consecutive.pushBack( data_point );
187 
188  const std::string* key_ptr = &topic_name ;
189 
190  auto plot_pair = plot_map.user_defined.find( *key_ptr );
191  if( plot_pair == plot_map.user_defined.end() )
192  {
193  plot_pair = plot_map.addUserDefined( *key_ptr );
194  }
195  PlotDataAny& plot_raw = plot_pair->second;
196  plot_raw.pushBack( data_point );
197  //------------------------------------------
198  if( msg_count++ %100 == 0)
199  {
200  progress_dialog.setValue( msg_count );
201  QApplication::processEvents();
202 
203  if( progress_dialog.wasCanceled() ) {
204  return false;
205  }
206  }
207  //------------------------------------------
208  if( topic_selected.find( topic_name ) == topic_selected.end() )
209  {
210  continue;
211  }
212 
213  const size_t msg_size = msg_instance.size();
214  buffer.resize(msg_size);
215 
216  ros::serialization::OStream stream(buffer.data(), buffer.size());
217  msg_instance.write(stream);
218  MessageRef buffer_view( buffer );
219  _ros_parser.pushMessageRef( topic_name, buffer_view, msg_time );
220  }
221 
222  _ros_parser.extractData(plot_map, "");
223 
224  qDebug() << "The loading operation took" << timer.elapsed() << "milliseconds";
225 
227  return true;
228 }
229 
231 {
232 
233 }
234 
235 bool DataLoadROS::xmlSaveState(QDomDocument &doc, QDomElement &plugin_elem) const
236 {
237  QDomElement stamp_elem = doc.createElement("use_header_stamp");
238  stamp_elem.setAttribute("value", _config.use_header_stamp ? "true" : "false");
239  plugin_elem.appendChild( stamp_elem );
240 
241  QDomElement rename_elem = doc.createElement("use_renaming_rules");
242  rename_elem.setAttribute("value", _config.use_renaming_rules ? "true" : "false");
243  plugin_elem.appendChild( rename_elem );
244 
245  QDomElement discard_elem = doc.createElement("discard_large_arrays");
246  discard_elem.setAttribute("value", _config.discard_large_arrays ? "true" : "false");
247  plugin_elem.appendChild( discard_elem );
248 
249  QDomElement max_elem = doc.createElement("max_array_size");
250  max_elem.setAttribute("value", QString::number(_config.max_array_size));
251  plugin_elem.appendChild( max_elem );
252 
253  return true;
254 }
255 
256 bool DataLoadROS::xmlLoadState(const QDomElement &parent_element)
257 {
258  QDomElement stamp_elem = parent_element.firstChildElement( "use_header_stamp" );
259  _config.use_header_stamp = ( stamp_elem.attribute("value") == "true");
260 
261  QDomElement rename_elem = parent_element.firstChildElement( "use_renaming_rules" );
262  _config.use_renaming_rules = ( rename_elem.attribute("value") == "true");
263 
264  QDomElement discard_elem = parent_element.firstChildElement( "discard_large_arrays" );
265  _config.discard_large_arrays = ( discard_elem.attribute("value") == "true");
266 
267  QDomElement max_elem = parent_element.firstChildElement( "max_array_size" );
268  _config.max_array_size = max_elem.attribute("value").toInt();
269 
270  return true;
271 }
272 
274 {
275  QSettings settings;
276 
277  settings.setValue("DataLoadROS/default_topics", _config.selected_topics);
278  settings.setValue("DataLoadROS/use_renaming", _config.use_renaming_rules);
279  settings.setValue("DataLoadROS/use_header_stamp", _config.use_header_stamp);
280  settings.setValue("DataLoadROS/max_array_size", (int)_config.max_array_size);
281  settings.setValue("DataLoadROS/discard_large_arrays", _config.discard_large_arrays);
282 }
283 
284 
286 {
287  QSettings settings;
288 
289  _config.selected_topics = settings.value("DataLoadROS/default_topics", false ).toStringList();
290  _config.use_header_stamp = settings.value("DataLoadROS/use_header_stamp", false ).toBool();
291  _config.use_renaming_rules = settings.value("DataLoadROS/use_renaming", true ).toBool();
292  _config.max_array_size = settings.value("DataLoadROS/max_array_size", 100 ).toInt();
293  _config.discard_large_arrays = settings.value("DataLoadROS/discard_large_arrays", true ).toBool();
294 }
295 
std::vector< const char * > _extensions
Definition: dataload_ros.h:42
std::vector< std::pair< QString, QString > > getAndRegisterAllTopics()
void saveDefaultSettings()
static void registerMessage(const std::string &topic_name, const std::string &md5sum, const std::string &datatype, const std::string &definition)
std::vector< const ConnectionInfo * > getConnections()
QString filename
void pushBack(Point p)
Definition: plotdata.h:214
virtual bool xmlLoadState(const QDomElement &parent_element) override
std::unordered_map< std::string, PlotDataAny >::iterator addUserDefined(const std::string &name)
Definition: plotdata.h:156
virtual bool xmlSaveState(QDomDocument &doc, QDomElement &parent_element) const override
std::unordered_map< std::string, PlotDataAny > user_defined
Definition: plotdata.h:145
uint32_t size()
RosMessageParser _ros_parser
Definition: dataload_ros.h:40
void setMaxArrayPolicy(size_t max_array_size, bool discard_entire_array)
Definition: ros_parser.cpp:58
void loadDefaultSettings()
void pushMessageRef(const std::string &topic_name, const MessageRef &msg, double timestamp) override
Definition: ros_parser.cpp:104
static RosIntrospection::SubstitutionRuleMap getRenamingRules()
void StrCat(const std::string &a, const std::string &b, std::string &out)
virtual void extractData(PlotDataMapRef &destination, const std::string &prefix) override
Definition: ros_parser.cpp:240
Configuration getResult() const
ROSTIME_DECL const Time TIME_MAX
virtual ~DataLoadROS() override
QStringList selected_datasources
virtual const std::vector< const char * > & compatibleFileExtensions() const override
ROSTIME_DECL const Time TIME_MIN
std::shared_ptr< rosbag::Bag > _bag
Definition: dataload_ros.h:37
DialogSelectRosTopics::Configuration _config
Definition: dataload_ros.h:44
virtual bool readDataFromFile(FileLoadInfo *fileload_info, PlotDataMapRef &destination) override
void setUseHeaderStamp(bool use)
QDomDocument plugin_config
void addRules(const RosIntrospection::SubstitutionRuleMap &rules)
Definition: ros_parser.h:17
bool registerSchema(const std::string &topic_name, const std::string &md5sum, RosIntrospection::ROSType type, const std::string &definition)
Definition: ros_parser.cpp:83


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:17