RTXI  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 
23 static Workspace::variable_t vars[] =
24 {
25  { "Comp Time (ns)", "", Workspace::STATE, },
26  { "Peak Comp Time (ns)", "", Workspace::STATE, },
27  { "Real-time Period (ns)", "", Workspace::STATE, },
28  { "Peak RT Period (ns)", "", Workspace::STATE, },
29  { "RT Jitter (ns)", "", Workspace::STATE, },
30 };
31 
32 static size_t num_vars = sizeof(vars) / sizeof(Workspace::variable_t); // Required variable (number of variables)
33 
34 PerformanceMeasurement::Panel::Panel(QWidget *parent) : QWidget(parent),
35  Workspace::Instance("Performance Measurement", vars, num_vars), state(INIT1), duration(0),
36  lastRead(0), timestep(0), maxDuration(0), maxTimestep(0), jitter(0)
37 {
38 
39  // Make Mdi
40  QMdiSubWindow *subWindow = new QMdiSubWindow;
41  subWindow->setWindowIcon(QIcon("/usr/local/share/rtxi/RTXI-widget-icon.png"));
42  subWindow->setAttribute(Qt::WA_DeleteOnClose);
43  subWindow->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint |
44  Qt::WindowMinimizeButtonHint);
45  MainWindow::getInstance()->createMdi(subWindow);
46 
47  // Create main layout
48  QVBoxLayout *layout = new QVBoxLayout;
49  QString suffix = QString("s)").prepend(QChar(0x3BC));
50 
51  // Create child widget and gridLayout
52  QGridLayout *gridLayout = new QGridLayout;
53 
54  durationEdit = new QLineEdit(subWindow);
55  durationEdit->setReadOnly(true);
56  gridLayout->addWidget(new QLabel(tr("Computation Time (").append(suffix)), 1, 0);
57  gridLayout->addWidget(durationEdit, 1, 1);
58 
59  maxDurationEdit = new QLineEdit(subWindow);
60  maxDurationEdit->setReadOnly(true);
61  gridLayout->addWidget(new QLabel(tr("Peak Computation Time (").append(suffix)), 2, 0);
62  gridLayout->addWidget(maxDurationEdit, 2, 1);
63 
64  timestepEdit = new QLineEdit(subWindow);
65  timestepEdit->setReadOnly(true);
66  gridLayout->addWidget(new QLabel(tr("Real-time Period (").append(suffix)), 3, 0);
67  gridLayout->addWidget(timestepEdit, 3, 1);
68 
69  maxTimestepEdit = new QLineEdit(subWindow);
70  maxTimestepEdit->setReadOnly(true);
71  gridLayout->addWidget(new QLabel(tr("Peak Real-time Period (").append(suffix)), 4, 0);
72  gridLayout->addWidget(maxTimestepEdit, 4, 1);
73 
74  timestepJitterEdit = new QLineEdit(subWindow);
75  timestepJitterEdit->setReadOnly(true);
76  gridLayout->addWidget(new QLabel(tr("Real-time Jitter (").append(suffix)), 5, 0);
77  gridLayout->addWidget(timestepJitterEdit, 5, 1);
78 
79  QPushButton *resetButton = new QPushButton("Reset", this);
80  gridLayout->addWidget(resetButton, 6, 1);
81  QObject::connect(resetButton,SIGNAL(released(void)),this,SLOT(reset(void)));
82 
83  // Attach child widget to parent widget
84  layout->addLayout(gridLayout);
85 
86  // Attach gridLayout to Widget
87  setLayout(layout);
88  setWindowTitle(QString::number(getID()) + tr(" RT Benchmarks"));
89 
90  // Set layout to Mdi
91  subWindow->setWidget(this);
92  subWindow->setFixedSize(subWindow->minimumSizeHint());
93  show();
94 
95  QTimer *timer = new QTimer(this);
96  timer->setTimerType(Qt::PreciseTimer);
97  timer->start(1000);
98  QObject::connect(timer,SIGNAL(timeout(void)),this,SLOT(update(void)));
99 
100  // Connect states to workspace
101  setData(Workspace::STATE, 0, &duration);
102  setData(Workspace::STATE, 1, &maxDuration);
103  setData(Workspace::STATE, 2, &timestep);
104  setData(Workspace::STATE, 3, &maxTimestep);
105  setData(Workspace::STATE, 4, &jitter);
106 
107  setActive(true);
108 }
109 
111 {
112  Plugin::getInstance()->panel = 0;
113 }
114 
116 {
117  long long now = RT::OS::getTime();
118  double period = RT::System::getInstance()->getPeriod();
119 
120  switch (state)
121  {
122  case EXEC:
123  if (maxTimestep < now - lastRead)
124  maxTimestep = now - lastRead;
125  timestep = now - lastRead;
126  latency = (now - lastRead) - period;
127  timestepStat.push(timestep);
128  latencyStat.push(latency);
129  break;
130  case INIT2:
131  timestep = maxTimestep = now - lastRead;
132  latency = maxLatency = (now - lastRead) - period;
133  timestepStat.push(timestep);
134  latencyStat.push(latency);
135  state = EXEC;
136  break;
137  case INIT1:
138  state = INIT2;
139  }
140  lastRead = now;
141  jitter = latencyStat.std();
142 }
143 
145 {
146  long long now = RT::OS::getTime();
147  double period = RT::System::getInstance()->getPeriod();
148 
149  switch (state)
150  {
151  case EXEC:
152  if (maxDuration < now - lastRead)
153  {
154  maxDuration = now - lastRead;
155  }
156  duration = now - lastRead;
157  break;
158  case INIT2:
159  duration = maxDuration = now - lastRead;
160  break;
161  default:
162  ERROR_MSG("PerformanceMeasurement::Panel::write : invalid state\n");
163  }
164 }
165 
167 {
168  state = INIT1;
169  timestepStat.clear();
170  latencyStat.clear();
171 }
172 
174 {
175  maxTimestep = timestep;
176 }
177 
179 {
180  durationEdit->setText(QString::number(duration * 1e-3));
181  maxDurationEdit->setText(QString::number(maxDuration * 1e-3));
182  timestepEdit->setText(QString::number(timestep * 1e-3));
183  maxTimestepEdit->setText(QString::number(maxTimestep * 1e-3));
184  timestepJitterEdit->setText(QString::number(jitter * 1e-3));
185 }
186 
187 extern "C" Plugin::Object * createRTXIPlugin(void *)
188 {
190 }
191 
193 {
195 }
196 
198 {
199  if (panel)
200  delete panel;
201  instance = 0;
202  panel = 0;
203 }
204 
205 void
207 {
208  if (!panel)
209  panel = new Panel(MainWindow::getInstance()->centralWidget());
210  panel->show();
211 }
212 
213 static Mutex mutex;
215 
217 {
218  if (instance)
219  return instance;
220 
221  /*************************************************************************
222  * Seems like alot of hoops to jump through, but allocation isn't *
223  * thread-safe. So effort must be taken to ensure mutual exclusion. *
224  *************************************************************************/
225 
226  Mutex::Locker lock(&::mutex);
227  if (!instance)
228  instance = new Plugin();
229 
230  return instance;
231 }
static MainWindow * getInstance(void)
long long getPeriod(void) const
Definition: rt.h:392
void setActive(bool)
Definition: rt.cpp:130
Definition: mutex.h:28
#define ERROR_MSG(fmt, args...)
Definition: debug.h:41
long long getTime(void)
void createMdi(QMdiSubWindow *)
void setData(IO::flags_t type, size_t index, double *value)
Definition: workspace.cpp:272
ID getID(void) const
Definition: settings.h:131
Internal Control Oriented Classes.
Definition: workspace.h:30
Plugin::Object * createRTXIPlugin(void *)
static System * getInstance(void)
Definition: rt.cpp:361
QAction * createSystemMenuItem(const QString &label, const QObject *handler, const char *slot)
Classes associated with the loading/unloading of binaries at run-time.
Definition: plugin.h:35