ros_source.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2015, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
00021 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00023 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00024 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00027 // DAMAGE.
00028 //
00029 // *****************************************************************************
00030 #include <swri_profiler_tools/ros_source.h>
00031 #include <swri_profiler_tools/ros_source_backend.h>
00032 #include <swri_profiler_tools/profile_database.h>
00033 
00034 namespace swri_profiler_tools
00035 {
00036 static const QString LIVE_PROFILE_NAME = "ROS Capture [current]";
00037 static const QString DEAD_PROFILE_NAME = "ROS Capture";
00038 
00039 RosSource::RosSource(ProfileDatabase *db)
00040   :
00041   db_(db),
00042   backend_(NULL),
00043   profile_key_(-1),
00044   connected_(false)
00045 {
00046 }
00047 
00048 RosSource::~RosSource()
00049 {
00050   ros_thread_.quit();
00051   if (!ros_thread_.wait(500)) {
00052     qWarning("ROS thread is not closing in timely fashion.  This can happen "
00053              "when the network connection is lost or ROS master has shutdown. "
00054              "We will attempt to forcibly terminate the thread.");
00055     ros_thread_.terminate();
00056   }
00057 }
00058 
00059 void RosSource::start()
00060 {
00061   if (backend_) {
00062     return;
00063   }
00064   
00065   // We run the backend in another thread.  Aside from starting up the
00066   // backend, this object's main function is to keep track of state
00067   // and provide access to that information without having to deal
00068   // with thread-safe data access.
00069   backend_ = new RosSourceBackend();
00070   backend_->moveToThread(&ros_thread_);
00071 
00072   QObject::connect(&ros_thread_, SIGNAL(finished()),
00073                    backend_, SLOT(deleteLater()));
00074   
00075   QObject::connect(backend_, SIGNAL(connected(bool, QString)),
00076                    this, SLOT(handleConnected(bool, QString)));
00077   QObject::connect(backend_, SIGNAL(indexReceived(swri_profiler_msgs::ProfileIndexArray)),
00078                    this, SLOT(handleIndex(swri_profiler_msgs::ProfileIndexArray)));
00079   QObject::connect(backend_, SIGNAL(dataReceived(swri_profiler_msgs::ProfileDataArray)),
00080                    this, SLOT(handleData(swri_profiler_msgs::ProfileDataArray)));
00081 
00082   ros_thread_.start();
00083 }
00084 
00085 void RosSource::handleConnected(bool is_connected, QString uri)
00086 {
00087   connected_ = is_connected;
00088   master_uri_ = uri;
00089   Q_EMIT connected(connected_, master_uri_);
00090 
00091   if (!connected_) {
00092     msg_adapter_.reset();
00093 
00094     if (profile_key_ >= 0) {
00095       Profile &profile = db_->profile(profile_key_);
00096       if (profile.isValid() && profile.name() == LIVE_PROFILE_NAME) {
00097         profile.setName(DEAD_PROFILE_NAME);
00098       }
00099     }      
00100     profile_key_ = -1;
00101   }
00102 }
00103 
00104 void RosSource::handleIndex(swri_profiler_msgs::ProfileIndexArray msg)
00105 {
00106   msg_adapter_.processIndex(msg);
00107 }
00108 
00109 void RosSource::handleData(swri_profiler_msgs::ProfileDataArray msg)
00110 {
00111   NewProfileDataVector new_data;
00112   if (!msg_adapter_.processData(new_data, msg)) {
00113     return;
00114   }
00115 
00116   // todo(elliotjo): If we detect a large gap, we should create a new
00117   // profile for the data to handle the use case of leaving the
00118   // profiler open throughout a development session.  We should also
00119   // consider the case where data is coming from a computer with a bad
00120   // clock.  We'll either allocate a huge timespan or constantly
00121   // generate new profiles.  Either are really bad.
00122   
00123   if (profile_key_ < 0) {
00124     profile_key_ = db_->createProfile(LIVE_PROFILE_NAME);
00125     if (profile_key_ < 0) {
00126       qWarning("Failed to create a new profile. Dropping data.");
00127       return;
00128     }
00129   }
00130   
00131   db_->profile(profile_key_).addData(new_data);
00132 }
00133 }  // namespace swri_profiler_tools


swri_profiler_tools
Author(s):
autogenerated on Sat Apr 27 2019 03:08:49