RTXI  2.4
The Real-Time eXperiment Interface Documentation
performance_measurement.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
3 
4  This program is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17  */
18 
19 #include <debug.h>
20 #include <main_window.h>
22 #include <rt.h>
23 
24 
25 static Workspace::variable_t vars[] =
26 {
27  { "Comp Time (ns)", "", Workspace::STATE, },
28  { "Peak Comp Time (ns)", "", Workspace::STATE, },
29  { "Real-time Period (ns)", "", Workspace::STATE, },
30  { "Peak RT Period (ns)", "", Workspace::STATE, },
31  { "RT Jitter (ns)", "", Workspace::STATE, },
32 };
33 
34 static size_t num_vars = sizeof(vars) / sizeof(Workspace::variable_t); // Required variable (number of variables)
35 
36 PerformanceMeasurement::Panel::Panel(QWidget *parent) : QWidget(parent),
37  Workspace::Instance("Performance Measurement", vars, num_vars), state(INIT1), duration(0),
38  lastRead(0), timestep(0), maxDuration(0), maxTimestep(0), jitter(0)
39 {
40 
41  // Make Mdi
42  QMdiSubWindow *subWindow = new QMdiSubWindow;
43  subWindow->setWindowIcon(QIcon("/usr/local/share/rtxi/RTXI-widget-icon.png"));
44  subWindow->setAttribute(Qt::WA_DeleteOnClose);
45  subWindow->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint |
46  Qt::WindowMinimizeButtonHint);
47  MainWindow::getInstance()->createMdi(subWindow);
48 
49  // Create main layout
50  QVBoxLayout *layout = new QVBoxLayout;
51  QString suffix = QString("s)").prepend(QChar(0x3BC));
52 
53  // Create child widget and gridLayout
54  QGridLayout *gridLayout = new QGridLayout;
55 
56  durationEdit = new QLineEdit(subWindow);
57  durationEdit->setReadOnly(true);
58  gridLayout->addWidget(new QLabel(tr("Computation Time (").append(suffix)), 1, 0);
59  gridLayout->addWidget(durationEdit, 1, 1);
60 
61  maxDurationEdit = new QLineEdit(subWindow);
62  maxDurationEdit->setReadOnly(true);
63  gridLayout->addWidget(new QLabel(tr("Peak Computation Time (").append(suffix)), 2, 0);
64  gridLayout->addWidget(maxDurationEdit, 2, 1);
65 
66  timestepEdit = new QLineEdit(subWindow);
67  timestepEdit->setReadOnly(true);
68  gridLayout->addWidget(new QLabel(tr("Real-time Period (").append(suffix)), 3, 0);
69  gridLayout->addWidget(timestepEdit, 3, 1);
70 
71  maxTimestepEdit = new QLineEdit(subWindow);
72  maxTimestepEdit->setReadOnly(true);
73  gridLayout->addWidget(new QLabel(tr("Peak Real-time Period (").append(suffix)), 4, 0);
74  gridLayout->addWidget(maxTimestepEdit, 4, 1);
75 
76  timestepJitterEdit = new QLineEdit(subWindow);
77  timestepJitterEdit->setReadOnly(true);
78  gridLayout->addWidget(new QLabel(tr("Real-time Jitter (").append(suffix)), 5, 0);
79  gridLayout->addWidget(timestepJitterEdit, 5, 1);
80 
81  AppCpuPercentEdit = new QLineEdit(subWindow);
82  AppCpuPercentEdit->setReadOnly(true);
83  gridLayout->addWidget(new QLabel("RTXI App Cpu Usage(%)"), 6, 0);
84  gridLayout->addWidget(AppCpuPercentEdit, 6, 1);
85 
86  QPushButton *resetButton = new QPushButton("Reset", this);
87  gridLayout->addWidget(resetButton, 7, 1);
88  QObject::connect(resetButton,SIGNAL(released(void)),this,SLOT(reset(void)));
89 
90  // Attach child widget to parent widget
91  layout->addLayout(gridLayout);
92 
93  // Attach gridLayout to Widget
94  setLayout(layout);
95  setWindowTitle(QString::number(getID()) + tr(" RT Benchmarks"));
96 
97  // Set layout to Mdi
98  subWindow->setWidget(this);
99  subWindow->setFixedSize(subWindow->minimumSizeHint());
100  show();
101 
102  QTimer *timer = new QTimer(this);
103  timer->setTimerType(Qt::PreciseTimer);
104  timer->start(1000);
105  QObject::connect(timer,SIGNAL(timeout(void)),this,SLOT(update(void)));
106 
107  // Connect states to workspace
108  setData(Workspace::STATE, 0, &duration);
109  setData(Workspace::STATE, 1, &maxDuration);
110  setData(Workspace::STATE, 2, &timestep);
111  setData(Workspace::STATE, 3, &maxTimestep);
112  setData(Workspace::STATE, 4, &jitter);
113 
114  setActive(true);
115 }
116 
118 {
119  Plugin::getInstance()->panel = 0;
120 }
121 
123 {
124  long long now = RT::OS::getTime();
125  double period = RT::System::getInstance()->getPeriod();
126 
127  switch (state)
128  {
129  case EXEC:
130  if (maxTimestep < now - lastRead)
131  maxTimestep = now - lastRead;
132  timestep = now - lastRead;
133  latency = (now - lastRead) - period;
134  timestepStat.push(timestep);
135  latencyStat.push(latency);
136  break;
137  case INIT2:
138  timestep = maxTimestep = now - lastRead;
139  latency = maxLatency = (now - lastRead) - period;
140  timestepStat.push(timestep);
141  latencyStat.push(latency);
142  state = EXEC;
143  break;
144  case INIT1:
145  state = INIT2;
146  }
147  lastRead = now;
148  jitter = latencyStat.std();
149 }
150 
152 {
153  long long now = RT::OS::getTime();
154 
155  switch (state)
156  {
157  case EXEC:
158  if (maxDuration < now - lastRead)
159  {
160  maxDuration = now - lastRead;
161  }
162  duration = now - lastRead;
163  break;
164  case INIT2:
165  duration = maxDuration = now - lastRead;
166  break;
167  default:
168  ERROR_MSG("PerformanceMeasurement::Panel::write : invalid state\n");
169  }
170 }
171 
173 {
174  state = INIT1;
175  timestepStat.clear();
176  latencyStat.clear();
177 }
178 
180 {
181  maxTimestep = timestep;
182 }
183 
185 {
186  durationEdit->setText(QString::number(duration * 1e-3));
187  maxDurationEdit->setText(QString::number(maxDuration * 1e-3));
188  timestepEdit->setText(QString::number(timestep * 1e-3));
189  maxTimestepEdit->setText(QString::number(maxTimestep * 1e-3));
190  timestepJitterEdit->setText(QString::number(jitter * 1e-3));
191  AppCpuPercentEdit->setText(QString::number(RT::OS::getCpuUsage()));
192 }
193 
194 extern "C" Plugin::Object * createRTXIPlugin(void *)
195 {
197 }
198 
199 PerformanceMeasurement::Plugin::Plugin(void) : panel(0)
200 {
201  MainWindow::getInstance()->createSystemMenuItem("RT Benchmarks",this,SLOT(createPerformanceMeasurementPanel(void)));
202 }
203 
204 PerformanceMeasurement::Plugin::~Plugin(void)
205 {
206  if (panel)
207  delete panel;
208  instance = 0;
209  panel = 0;
210 }
211 
212 void
214 {
215  if (!panel)
216  panel = new Panel(MainWindow::getInstance()->centralWidget());
217  panel->show();
218 }
219 
220 static Mutex mutex;
221 PerformanceMeasurement::Plugin *PerformanceMeasurement::Plugin::instance = 0;
222 
224 {
225  if (instance)
226  return instance;
227 
228  /*************************************************************************
229  * Seems like alot of hoops to jump through, but allocation isn't *
230  * thread-safe. So effort must be taken to ensure mutual exclusion. *
231  *************************************************************************/
232 
233  Mutex::Locker lock(&::mutex);
234  if (!instance)
235  instance = new Plugin();
236 
237  return instance;
238 }
239 
PerformanceMeasurement::Panel::write
void write(void)
Definition: performance_measurement.cpp:151
MainWindow::createSystemMenuItem
QAction * createSystemMenuItem(const QString &label, const QObject *handler, const char *slot)
Definition: main_window.cpp:253
ERROR_MSG
void ERROR_MSG(const std::string &errmsg,...)
Definition: debug.cpp:27
Plugin::Object
Definition: plugin.h:145
MainWindow::createMdi
void createMdi(QMdiSubWindow *)
Definition: main_window.cpp:230
PerformanceMeasurement::Plugin::createPerformanceMeasurementPanel
void createPerformanceMeasurementPanel(void)
Definition: performance_measurement.cpp:213
RT::System::getPeriod
long long getPeriod(void) const
Definition: rt.h:404
PerformanceMeasurement::Plugin::getInstance
static Plugin * getInstance(void)
Definition: performance_measurement.cpp:223
RT::OS::getTime
long long getTime(void)
Definition: rt_os-posix.cpp:143
RT::System::getInstance
static System * getInstance(void)
Definition: rt.cpp:361
PerformanceMeasurement::Plugin
Definition: performance_measurement.h:38
Mutex
Definition: mutex.h:28
PerformanceMeasurement::Panel::reset
void reset(void)
Definition: performance_measurement.cpp:172
PerformanceMeasurement::Panel::~Panel
virtual ~Panel(void)
Definition: performance_measurement.cpp:117
PerformanceMeasurement::Panel::resetMaxTimeStep
void resetMaxTimeStep(void)
Definition: performance_measurement.cpp:179
IO::channel_t
Definition: io.h:56
Workspace
Internal Control Oriented Classes.
Definition: workspace.h:30
RT::OS::getCpuUsage
double getCpuUsage(void)
Definition: rt_os-posix.cpp:183
rt.h
Plugin
Classes associated with the loading/unloading of binaries at run-time.
Definition: plugin.h:35
Mutex::Locker
Definition: mutex.h:36
Workspace::Instance::setData
void setData(IO::flags_t type, size_t index, double *value)
Definition: workspace.cpp:272
createRTXIPlugin
Plugin::Object * createRTXIPlugin(void *)
Definition: performance_measurement.cpp:194
MainWindow::getInstance
static MainWindow * getInstance(void)
Definition: main_window.cpp:454
PerformanceMeasurement::Panel::read
void read(void)
Definition: performance_measurement.cpp:122
PerformanceMeasurement::Panel::update
void update(void)
Definition: performance_measurement.cpp:184
PerformanceMeasurement::Panel
Definition: performance_measurement.h:61
Settings::Object::getID
ID getID(void) const
Definition: settings.h:131
performance_measurement.h
RT::Device::setActive
void setActive(bool)
Definition: rt.cpp:130
debug.h
PerformanceMeasurement::Panel::Panel
Panel(QWidget *)
Definition: performance_measurement.cpp:36
main_window.h