RTXI  3.0.0
The Real-Time eXperiment Interface Reference Manual
performance_measurement.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Will
3  Cornell Medical College
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  */
19 
20 #include <functional>
21 
23 
24 #include "debug.hpp"
25 #include "event.hpp"
26 #include "main_window.hpp"
27 #include "rt.hpp"
28 #include "widgets.hpp"
29 
30 PerformanceMeasurement::Panel::Panel(const std::string& mod_name,
31  QMainWindow* mwindow,
32  Event::Manager* ev_manager)
33  : Widgets::Panel(mod_name, mwindow, ev_manager)
34  , durationEdit(new QLineEdit(this))
35  , timestepEdit(new QLineEdit(this))
36  , maxDurationEdit(new QLineEdit(this))
37  , maxTimestepEdit(new QLineEdit(this))
38  , timestepJitterEdit(new QLineEdit(this))
39  , AppCpuPercentEdit(new QLineEdit(this))
40 {
41  // Create main layout
42  // auto* box_layout = new QVBoxLayout;
43  const QString suffix = QString("s)").prepend(QChar(0x3BC));
44 
45  // Create child widget and gridLayout
46  auto* gridLayout = new QGridLayout;
47 
48  durationEdit->setReadOnly(true);
49  gridLayout->addWidget(
50  new QLabel(tr("Computation Time (").append(suffix)), 1, 0);
51  gridLayout->addWidget(durationEdit, 1, 1);
52 
53  maxDurationEdit->setReadOnly(true);
54  gridLayout->addWidget(
55  new QLabel(tr("Peak Computation Time (").append(suffix)), 2, 0);
56  gridLayout->addWidget(maxDurationEdit, 2, 1);
57 
58  timestepEdit->setReadOnly(true);
59  gridLayout->addWidget(
60  new QLabel(tr("Real-time Period (").append(suffix)), 3, 0);
61  gridLayout->addWidget(timestepEdit, 3, 1);
62 
63  maxTimestepEdit->setReadOnly(true);
64  gridLayout->addWidget(
65  new QLabel(tr("Peak Real-time Period (").append(suffix)), 4, 0);
66  gridLayout->addWidget(maxTimestepEdit, 4, 1);
67 
68  timestepJitterEdit->setReadOnly(true);
69  gridLayout->addWidget(
70  new QLabel(tr("Real-time Jitter (").append(suffix)), 5, 0);
71  gridLayout->addWidget(timestepJitterEdit, 5, 1);
72 
73  AppCpuPercentEdit->setReadOnly(true);
74  gridLayout->addWidget(new QLabel("RTXI App Cpu Usage(%)"), 6, 0);
75  gridLayout->addWidget(AppCpuPercentEdit, 6, 1);
76 
77  auto* resetButton = new QPushButton("Reset", this);
78  gridLayout->addWidget(resetButton, 7, 1);
79  QObject::connect(resetButton, SIGNAL(released()), this, SLOT(reset()));
80 
81  // Attach child widget to parent widget
82  // box_layout->addLayout(gridLayout);
83 
84  // Attach gridLayout to Widget
85  setLayout(gridLayout);
86  setWindowTitle(tr(std::string(PerformanceMeasurement::MODULE_NAME).c_str()));
87 
88  // Set layout to Mdi
89  this->getMdiWindow()->setFixedSize(this->minimumSizeHint());
90  auto* timer = new QTimer(this);
91  timer->setInterval(1000);
92  QObject::connect(
93  timer, &QTimer::timeout, this, &PerformanceMeasurement::Panel::refresh);
94  timer->start();
95 }
96 
98  : Widgets::Component(hplugin,
99  std::string(MODULE_NAME),
100  std::vector<IO::channel_t>(),
102 {
103  if (RT::OS::getFifo(this->fifo,
105  < 0)
106  {
107  ERROR_MSG(
108  "PerformanceMeasurement::Component::Component : Unable to craate "
109  "component fifo");
110  this->setState(RT::State::PAUSE);
111  }
112 }
113 
115 {
116  auto period = RT::OS::getPeriod();
117  if (period < 0) {
118  period = RT::OS::DEFAULT_PERIOD;
119  }
120 
121  stats.duration = static_cast<double>(*(end_ticks) - *(start_ticks));
122  stats.timestep = static_cast<double>(*(start_ticks)-last_start_ticks);
123  stats.latency = stats.timestep - static_cast<double>(period);
124  stats.max_timestep = std::max(stats.max_timestep, stats.timestep);
125  stats.max_duration = std::max(stats.max_duration, stats.duration);
126  stats.max_latency = std::max(stats.max_latency, stats.latency);
127  latencyStat.push(stats.latency);
128  stats.jitter = latencyStat.std();
129 
130  switch (this->getState()) {
131  case RT::State::EXEC:
132  this->fifo->writeRT(&this->stats,
134  break;
135  case RT::State::INIT:
136  latencyStat.clear();
137  latencyStat.push(0.0);
138  this->stats = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
139  this->setState(RT::State::EXEC);
140  break;
141  case RT::State::PERIOD:
142  this->setState(RT::State::INIT);
143  break;
144  case RT::State::MODIFY:
145  case RT::State::PAUSE:
146  case RT::State::UNPAUSE:
147  case RT::State::EXIT:
148  break;
149  }
150  last_start_ticks = *start_ticks;
151 }
152 
154  int64_t* e_ticks)
155 {
156  this->start_ticks = s_ticks;
157  this->end_ticks = e_ticks;
158 }
159 
161 {
162  auto* hostplugin =
163  dynamic_cast<PerformanceMeasurement::Plugin*>(this->getHostPlugin());
164  const double nano2micro = 1e-3;
166  hostplugin->getSampleStat();
167  durationEdit->setText(QString::number(stats.duration * nano2micro));
168  maxDurationEdit->setText(QString::number(stats.max_duration * nano2micro));
169  timestepEdit->setText(QString::number(stats.timestep * nano2micro));
170  maxTimestepEdit->setText(QString::number(stats.max_timestep * nano2micro));
171  timestepJitterEdit->setText(QString::number(stats.jitter * nano2micro));
172  AppCpuPercentEdit->setText(QString::number(RT::OS::getCpuUsage()));
173 }
174 
176 {
177  this->update_state(RT::State::INIT);
178 }
179 
181  : Widgets::Plugin(ev_manager,
182  std::string(PerformanceMeasurement::MODULE_NAME))
183 {
184  auto component = std::make_unique<PerformanceMeasurement::Component>(this);
185  std::vector<Event::Object> events;
186  events.emplace_back(Event::Type::RT_PREPERIOD_EVENT);
187  events.emplace_back(Event::Type::RT_POSTPERIOD_EVENT);
188  this->getEventManager()->postEvent(events);
189  auto* performance_measurement_component =
190  dynamic_cast<PerformanceMeasurement::Component*>(component.get());
191  performance_measurement_component->setTickPointers(
192  std::any_cast<int64_t*>(events[0].getParam("pre-period")),
193  std::any_cast<int64_t*>(events[1].getParam("post-period")));
194 
195  this->component_fifo = component->getFIfoPtr();
196  this->attachComponent(std::move(component));
197 }
198 
201 {
203  while (this->component_fifo->read(
205  > 0)
206  {
207  };
208  return stat;
209 }
210 
211 std::unique_ptr<Widgets::Plugin> PerformanceMeasurement::createRTXIPlugin(
212  Event::Manager* ev_manager)
213 {
214  return std::make_unique<PerformanceMeasurement::Plugin>(ev_manager);
215 }
216 
218  QMainWindow* main_window, Event::Manager* ev_manager)
219 {
220  return static_cast<Widgets::Panel*>(new PerformanceMeasurement::Panel(
222  main_window,
223  ev_manager));
224 }
225 
226 std::unique_ptr<Widgets::Component> PerformanceMeasurement::createRTXIComponent(
227  Widgets::Plugin* /*host_plugin*/)
228 {
229  return std::make_unique<PerformanceMeasurement::Component>(nullptr);
230 }
231 
233 {
238  return fact;
239 }
void postEvent(Object *event)
Definition: event.cpp:299
void setTickPointers(int64_t *s_ticks, int64_t *e_ticks)
Panel(const std::string &mod_name, QMainWindow *mwindow, Event::Manager *ev_manager)
Plugin(Event::Manager *ev_manager)
void setState(RT::State::state_t state)
Definition: widgets.hpp:249
QMdiSubWindow * getMdiWindow()
Definition: widgets.hpp:286
void attachComponent(std::unique_ptr< Widgets::Component > component)
Definition: widgets.cpp:504
Event::Manager * getEventManager()
Definition: widgets.cpp:589
void ERROR_MSG(const std::string &errmsg, Args... args)
Definition: debug.hpp:36
@ RT_PREPERIOD_EVENT
Definition: event.hpp:57
@ RT_POSTPERIOD_EVENT
Definition: event.hpp:58
Connection Oriented Classes.
Definition: io.hpp:40
struct IO::channel_t channel_t
Widgets::FactoryMethods getFactories()
std::unique_ptr< Widgets::Plugin > createRTXIPlugin(Event::Manager *ev_manager)
Widgets::Panel * createRTXIPanel(QMainWindow *main_window, Event::Manager *ev_manager)
std::vector< Widgets::Variable::Info > get_default_vars()
constexpr std::string_view MODULE_NAME
std::unique_ptr< Widgets::Component > createRTXIComponent(Widgets::Plugin *host_plugin)
int64_t getPeriod()
Definition: rtos_evl.cpp:150
int getFifo(std::unique_ptr< Fifo > &fifo, size_t fifo_size)
Definition: fifo.cpp:194
const int64_t DEFAULT_PERIOD
Definition: rtos.hpp:19
double getCpuUsage()
@ EXIT
Definition: rt.hpp:60
@ EXEC
Definition: rt.hpp:55
@ UNPAUSE
Definition: rt.hpp:59
@ PAUSE
Definition: rt.hpp:58
@ INIT
Definition: rt.hpp:54
@ MODIFY
Definition: rt.hpp:56
@ PERIOD
Definition: rt.hpp:57
Definition: rt.hpp:35
std::unique_ptr< Widgets::Plugin >(* createPlugin)(Event::Manager *)
Function that returns a smart pointer to plugin object.
Definition: widgets.hpp:145
Widgets::Panel *(* createPanel)(QMainWindow *, Event::Manager *)
Definition: widgets.hpp:170
std::unique_ptr< Widgets::Component >(* createComponent)(Widgets::Plugin *)
Definition: widgets.hpp:156