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 #include <rosbag/bag.h>
00007
00008 RosoutPublisher::RosoutPublisher():
00009 _enabled(false ),
00010 _tablemodel(nullptr),
00011 _log_window(nullptr)
00012 {
00013
00014 }
00015
00016 RosoutPublisher::~RosoutPublisher()
00017 {
00018
00019 }
00020
00021
00022 void RosoutPublisher::setEnabled(bool to_enable)
00023 {
00024 _enabled = to_enable;
00025
00026 if( enabled())
00027 {
00028 _minimum_time_usec = std::numeric_limits<int64_t>::max();
00029 _maximum_time_usec = std::numeric_limits<int64_t>::min();
00030
00031 if( _tablemodel == nullptr ){
00032 _tablemodel = new LogsTableModel(this);
00033 }
00034
00035 _log_window = new RosoutWindow();
00036
00037 auto logwidget = new rqt_console_plus::LogWidget( *_tablemodel, _log_window);
00038 _log_window->setCentralWidget( logwidget );
00039 Qt::WindowFlags flags = _log_window->windowFlags();
00040 _log_window->setWindowFlags( flags | Qt::SubWindow );
00041
00042 connect( this, &RosoutPublisher::timeRangeChanged,
00043 logwidget, &rqt_console_plus::LogWidget::on_timeRangeChanged );
00044
00045 connect(_log_window, &RosoutWindow::closed,
00046 this, &RosoutPublisher::onWindowClosed );
00047
00048 QSettings settings;
00049 _log_window->restoreGeometry(settings.value("RosoutPublisher.geometry").toByteArray());
00050
00051 _log_window->show();
00052 }
00053 else{
00054 if( _log_window )
00055 {
00056 _log_window->close();
00057 }
00058 }
00059
00060 StatePublisher::setEnabled(_enabled);
00061 }
00062
00063 void RosoutPublisher::onWindowClosed()
00064 {
00065 QSettings settings;
00066 settings.setValue("RosoutPublisher.geometry", _log_window->saveGeometry());
00067
00068 if( _tablemodel ){
00069 _tablemodel->deleteLater();
00070 _tablemodel = nullptr;
00071 }
00072 if( _log_window ) {
00073 _log_window->deleteLater();
00074 _log_window = nullptr;
00075 }
00076 _enabled = false;
00077 }
00078
00079
00080 std::vector<const PlotDataAny *> RosoutPublisher::findRosoutTimeseries()
00081 {
00082 std::vector<const PlotDataAny*> logs_timeseries;
00083
00084 for(const auto& data_it: _datamap->user_defined )
00085 {
00086 const std::string& topic_name = data_it.first;
00087
00088
00089 const RosIntrospection::ShapeShifter* registered_shapeshifted_msg = RosIntrospectionFactory::get().getShapeShifter( topic_name );
00090 if( ! registered_shapeshifted_msg )
00091 {
00092 continue;
00093 }
00094
00095 if(registered_shapeshifted_msg->getMD5Sum() != std::string(ros::message_traits::MD5Sum< rosgraph_msgs::Log >::value()) )
00096 {
00097 continue;
00098 }
00099
00100 logs_timeseries.push_back( &data_it.second );
00101 }
00102
00103 return logs_timeseries;
00104 }
00105
00106 void RosoutPublisher::syncWithTableModel(const std::vector<const PlotDataAny*>& logs_timeseries)
00107 {
00108 const int64_t threshold_time = _maximum_time_usec;
00109
00110 std::vector<rosgraph_msgs::LogConstPtr> logs;
00111 logs.reserve(100);
00112
00113
00114 for(const PlotDataAny* type_erased_logs: logs_timeseries )
00115 {
00116 const int first_index = type_erased_logs->getIndexFromX( threshold_time );
00117
00118 if( first_index != -1)
00119 {
00120 for( int i=first_index; i< type_erased_logs->size(); i++)
00121 {
00122 const auto& any_msg = type_erased_logs->at(i);
00123 const nonstd::any& any_value = any_msg.y;
00124
00125 const bool isRawBuffer = any_value.type() == typeid( std::vector<uint8_t>);
00126 const bool isRosbagMessage = any_value.type() == typeid( rosbag::MessageInstance );
00127 std::vector<uint8_t> raw_buffer;
00128
00129 if( isRawBuffer){
00130 raw_buffer = nonstd::any_cast<std::vector<uint8_t>>( any_value );
00131 }
00132 else if( isRosbagMessage ){
00133 const rosbag::MessageInstance& msg_instance = nonstd::any_cast<rosbag::MessageInstance>( any_value );
00134 raw_buffer.resize( msg_instance.size() );
00135 ros::serialization::OStream stream(raw_buffer.data(), raw_buffer.size());
00136 msg_instance.write(stream);
00137 }
00138 else{
00139 continue;
00140 }
00141
00142 rosgraph_msgs::LogPtr p(boost::make_shared<rosgraph_msgs::Log>());
00143 ros::serialization::IStream stream(raw_buffer.data(), raw_buffer.size() );
00144 ros::serialization::deserialize(stream, *p);
00145
00146 int64_t usec = p->header.stamp.toNSec() / 1000;
00147 _minimum_time_usec = std::min( _minimum_time_usec, usec);
00148 _maximum_time_usec = std::max( _maximum_time_usec, usec);
00149
00150 if( usec >= threshold_time){
00151 logs.push_back( p );
00152 }
00153 }
00154 }
00155 }
00156 std::sort( logs.begin(), logs.end(),
00157 [](const rosgraph_msgs::LogConstPtr& a, const rosgraph_msgs::LogConstPtr& b)
00158 {
00159 return a->header.stamp < b->header.stamp;
00160 } );
00161 _tablemodel->push_back( logs );
00162 }
00163
00164 void RosoutPublisher::updateState(double current_time)
00165 {
00166 if(!_enabled && !_tablemodel) return;
00167
00168 std::vector<const PlotDataAny*> logs_timeseries = findRosoutTimeseries();
00169
00170 syncWithTableModel(logs_timeseries);
00171
00172 using namespace std::chrono;
00173 TimePoint p_min = TimePoint() + microseconds(_minimum_time_usec);
00174
00175 TimePoint p_curr = TimePoint() + microseconds( (int64_t)(current_time*1000000));
00176
00177 emit timeRangeChanged(p_min, p_curr);
00178 }