progress_bar.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2014, 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <swri_console_util/progress_bar.h>
00031 
00032 #include <ctime>
00033 #include <sstream>
00034 
00035 namespace swri_console_util
00036 {
00037   ProgressBar::ProgressBar() :
00038       paused_(false),
00039       percent_complete_(0),
00040       start_time_(ros::WallTime::now()),
00041       paused_time_(0)
00042   {
00043     SetupTerminal();
00044   }
00045 
00046   ProgressBar::~ProgressBar()
00047   {
00048     RestoreTerminal();
00049   }
00050 
00051   void ProgressBar::SetStartTime(const ros::WallTime& start_time)
00052   {
00053     start_time_ = start_time;
00054   }
00055 
00056   void ProgressBar::SetProgress(double percent_complete)
00057   {
00058     percent_complete_ = percent_complete;
00059   }
00060 
00061   void ProgressBar::PrintTime()
00062   {
00063     ros::WallTime current_time = ros::WallTime::now();
00064     ros::WallDuration elapsed = (current_time - start_time_) - paused_time_;
00065 
00066     if (percent_complete_ > 0)
00067     {
00068       ros::WallDuration time_left =
00069         (elapsed * (1.0 / percent_complete_)) - elapsed;
00070 
00071       if (paused_)
00072       {
00073         printf("\r [PAUSED]  %.2f%% Complete,   Elapsed: %s   Estimated Remaining: %s  \r",
00074             percent_complete_ * 100.0,
00075             GetTimeString(elapsed.toSec()).c_str(),
00076             GetTimeString(time_left.toSec()).c_str());
00077       }
00078       else
00079       {
00080         printf("\r [RUNNING] %.2f%% Complete,   Elapsed: %s   Estimated Remaining: %s  \r",
00081             percent_complete_ * 100.0,
00082             GetTimeString(elapsed.toSec()).c_str(),
00083             GetTimeString(time_left.toSec()).c_str());
00084       }
00085     }
00086     else
00087     {
00088       if (paused_)
00089       {
00090         printf("\r [PAUSED]  %.2f%% Complete,   Elapsed: %s                                   \r",
00091             percent_complete_ * 100.0,
00092             GetTimeString(elapsed.toSec()).c_str());
00093       }
00094       else
00095       {
00096         printf("\r [RUNNING] %.2f%% Complete,   Elapsed: %s                                   \r",
00097             percent_complete_ * 100.0,
00098             GetTimeString(elapsed.toSec()).c_str());
00099       }
00100     }
00101 
00102     fflush(stdout);
00103   }
00104 
00105   void ProgressBar::CheckForPause()
00106   {
00107     ros::WallTime start_pause = ros::WallTime::now();
00108     do
00109     {
00110       bool charsleftorpaused = true;
00111       while (charsleftorpaused && ros::ok())
00112       {
00113         switch (ReadCharFromStdin())
00114         {
00115           case ' ':
00116             paused_ = !paused_;
00117 
00118             if (paused_)
00119             {
00120               PrintTime();
00121             }
00122           case EOF:
00123             charsleftorpaused = paused_;
00124         }
00125       }
00126     }
00127     while (paused_ && ros::ok());
00128 
00129     paused_time_ += (ros::WallTime::now() - start_pause);
00130 
00131     PrintTime();
00132   }
00133 
00134   char ProgressBar::ReadCharFromStdin()
00135   {
00136     fd_set testfd = stdin_fdset_;
00137 
00138     timeval tv;
00139     tv.tv_sec  = 0;
00140     tv.tv_usec = 0;
00141 
00142     if (select(maxfd_, &testfd, NULL, NULL, &tv) <= 0)
00143     {
00144       return EOF;
00145     }
00146 
00147     return getc(stdin);
00148   }
00149 
00150   void ProgressBar::SetupTerminal()
00151   {
00152     const int fd = fileno(stdin);
00153     termios flags;
00154     tcgetattr(fd, &orig_flags_);
00155     flags = orig_flags_;
00156     flags.c_lflag &= ~ICANON;      // set raw (unset canonical modes)
00157     flags.c_cc[VMIN]  = 0;         // i.e. min 1 char for blocking, 0 chars for
00158                                    // non-blocking
00159     flags.c_cc[VTIME] = 0;         // block if waiting for char
00160     tcsetattr(fd, TCSANOW, &flags);
00161 
00162     FD_ZERO(&stdin_fdset_);
00163     FD_SET(fd, &stdin_fdset_);
00164     maxfd_ = fd + 1;
00165   }
00166 
00167   void ProgressBar::RestoreTerminal()
00168   {
00169     const int fd = fileno(stdin);
00170     tcsetattr(fd, TCSANOW, &orig_flags_);
00171   }
00172 
00173   std::string ProgressBar::GetTimeString(double seconds)
00174   {
00175     int days = static_cast<int>(seconds / 86400.0);
00176     seconds -= days * 86400.0;
00177 
00178     int hours = static_cast<int>(seconds / 3600.0);
00179     seconds -= hours * 3600.0;
00180 
00181     int minutes = static_cast<int>(seconds / 60.0);
00182     seconds -= minutes * 60.0;
00183 
00184     std::string time;
00185     std::string unit;
00186     if (days > 0)
00187     {
00188       time += IntToString(days, 2) + ":";
00189       unit = "d";
00190     }
00191 
00192     if (hours > 0 || !time.empty())
00193     {
00194       if (time.empty())
00195       {
00196         unit = "h";
00197       }
00198 
00199       time += IntToString(hours, 2) + ":";
00200     }
00201 
00202     if (minutes > 0 || !time.empty())
00203     {
00204       if (time.empty())
00205       {
00206         unit = "m";
00207       }
00208 
00209       time += IntToString(minutes, 2) + ":";
00210     }
00211 
00212     if (time.empty())
00213     {
00214       unit = "s";
00215     }
00216 
00217     time += IntToString(seconds, 2) + unit;
00218 
00219     return time;
00220   }
00221 
00222   std::string ProgressBar::IntToString(int64_t i, int width)
00223   {
00224     std::stringstream ss;
00225     std::string s;
00226     ss << std::setfill('0');
00227     ss << std::setw(width);
00228     ss << i;
00229     s = ss.str();
00230     return s;
00231   }
00232 }


swri_console_util
Author(s): Marc Alban
autogenerated on Thu Jun 6 2019 20:34:43