rosout_publisher.cpp
Go to the documentation of this file.
00001 #include "rosout_publisher.h"
00002 #include "PlotJuggler/any.hpp"
00003 #include "../shape_shifter_factory.hpp"
00004 #include "../qnodedialog.h"
00005 #include <QSettings>
00006 
00007 RosoutPublisher::RosoutPublisher():
00008     enabled_(false ),
00009     _tablemodel(nullptr)
00010 {
00011 
00012 }
00013 
00014 RosoutPublisher::~RosoutPublisher()
00015 {
00016 
00017 }
00018 
00019 
00020 void RosoutPublisher::setEnabled(bool to_enable)
00021 {
00022     enabled_ = to_enable;
00023 
00024     if( enabled())
00025     {
00026         _minimum_time_usec = std::numeric_limits<int64_t>::max();
00027         _maximum_time_usec = std::numeric_limits<int64_t>::min();
00028 
00029         if( _tablemodel == nullptr ){
00030           _tablemodel = new LogsTableModel(this);
00031         }
00032 
00033         _log_window = new RosoutWindow();
00034 
00035         auto logwidget = new rqt_console_plus::LogWidget( *_tablemodel, _log_window);
00036         _log_window->setCentralWidget( logwidget );
00037         Qt::WindowFlags flags = _log_window->windowFlags();
00038         _log_window->setWindowFlags( flags | Qt::SubWindow );
00039 
00040         connect( this, &RosoutPublisher::timeRangeChanged,
00041                  logwidget, &rqt_console_plus::LogWidget::on_timeRangeChanged );
00042 
00043         connect(_log_window, &RosoutWindow::closed,
00044                 this, &RosoutPublisher::onWindowClosed );
00045 
00046         QSettings settings( "IcarusTechnology", "PlotJuggler");
00047         _log_window->restoreGeometry(settings.value("RosoutPublisher.geometry").toByteArray());
00048 
00049         _log_window->show();
00050     }
00051     else{
00052         if( _log_window )
00053         {
00054             _log_window->close();
00055         }
00056     }
00057 }
00058 
00059 void RosoutPublisher::onWindowClosed()
00060 {
00061     QSettings settings( "IcarusTechnology", "PlotJuggler");
00062     settings.setValue("RosoutPublisher.geometry", _log_window->saveGeometry());
00063 
00064     if( _tablemodel ){
00065       _tablemodel->deleteLater();
00066       _tablemodel = nullptr;
00067     }
00068     if( _log_window ) {
00069       _log_window->deleteLater();
00070       _log_window = nullptr;
00071     }
00072     enabled_ = false;
00073 }
00074 
00075 
00076 std::vector<const PlotDataAny *> RosoutPublisher::findRosoutTimeseries(PlotDataMap *datamap)
00077 {
00078     std::vector<const PlotDataAny*> logs_timeseries;
00079 
00080     for(const auto& data_it:  datamap->user_defined )
00081     {
00082         const std::string&    topic_name = data_it.first;
00083 
00084         // check if I registered this message before
00085         const RosIntrospection::ShapeShifter* registered_shapeshifted_msg = RosIntrospectionFactory::get().getShapeShifter( topic_name );
00086         if( ! registered_shapeshifted_msg )
00087         {
00088             continue; // will not be able to use this anyway, just skip
00089         }
00090 
00091         if(registered_shapeshifted_msg->getMD5Sum() != std::string(ros::message_traits::MD5Sum< rosgraph_msgs::Log >::value()) )
00092         {
00093             continue; // it is NOT a rosgraph_msgs::Log
00094         }
00095 
00096         logs_timeseries.push_back( data_it.second.get() );
00097     }
00098 
00099     return logs_timeseries;
00100 }
00101 
00102 void RosoutPublisher::syncWithTableModel(const std::vector<const PlotDataAny*>& logs_timeseries)
00103 {
00104     const int64_t threshold_time = _maximum_time_usec;
00105 
00106     std::vector<rosgraph_msgs::LogConstPtr> logs;
00107     logs.reserve(100);
00108 
00109     // most of the time we expect logs_timeseries to have just 1 element
00110     for(const  PlotDataAny* type_erased_logs:  logs_timeseries )
00111     {
00112         const int first_index = type_erased_logs->getIndexFromX( threshold_time );
00113 
00114         if( first_index != -1)
00115         { 
00116             for( int i=first_index; i< type_erased_logs->size(); i++)
00117             {
00118                 auto        any_msg   = type_erased_logs->at(i);
00119                 nonstd::any any_value = any_msg.y;
00120 
00121                 std::vector<uint8_t> raw_buffer =  nonstd::any_cast<std::vector<uint8_t>>( any_value );
00122 
00123                 rosgraph_msgs::LogPtr p(boost::make_shared<rosgraph_msgs::Log>());
00124                 ros::serialization::IStream stream(raw_buffer.data(), raw_buffer.size() );
00125                 ros::serialization::deserialize(stream, *p);
00126 
00127                 int64_t usec = p->header.stamp.toNSec() / 1000;
00128                 _minimum_time_usec = std::min( _minimum_time_usec, usec);
00129                 _maximum_time_usec = std::max( _maximum_time_usec, usec);
00130 
00131                 if( usec >= threshold_time){
00132                     logs.push_back( p );
00133                 }
00134             } 
00135         }
00136     }
00137     std::sort( logs.begin(), logs.end(), [](const rosgraph_msgs::LogConstPtr& a, const rosgraph_msgs::LogConstPtr& b)
00138     {
00139         return a->header.stamp < b->header.stamp;
00140     } );
00141     _tablemodel->push_back( logs );
00142 }
00143 
00144 void RosoutPublisher::updateState(PlotDataMap *datamap, double current_time)
00145 {
00146     if(!enabled_ && !_tablemodel) return;
00147 
00148     std::vector<const PlotDataAny*> logs_timeseries = findRosoutTimeseries(datamap);
00149 
00150     syncWithTableModel(logs_timeseries);
00151 
00152     using namespace std::chrono;
00153     TimePoint p_min  = TimePoint() + microseconds(_minimum_time_usec);
00154     //TimePoint p_max  = TimePoint() + microseconds(_maximum_time_usec);
00155     TimePoint p_curr = TimePoint() + microseconds( (int64_t)(current_time*1000000));
00156 
00157     emit timeRangeChanged(p_min, p_curr);
00158 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:57