YARP
Yet Another Robot Platform
Ping.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
10 #include <yarp/os/Ping.h>
11 
12 #include <yarp/os/Bottle.h>
14 #include <yarp/os/Network.h>
15 #include <yarp/os/Port.h>
16 #include <yarp/os/Time.h>
17 #include <yarp/os/Vocab.h>
18 
19 #include <cmath>
20 #include <cstdio>
21 #include <mutex>
22 
23 using namespace yarp::os;
24 
25 namespace {
26 YARP_OS_LOG_COMPONENT(PING, "yarp.os.Ping")
27 }
28 
30 {
31  clear();
32 }
33 
35 {
36  tot = tot2 = 0;
37  ct = at = 0;
38  mu = 0;
39  sigma = 1e10;
40  // infinity would be better, but methods of getting infinity
41  // require awkward dependencies
42 }
43 
44 void Stat::add(double val)
45 {
46  tot += val;
47  tot2 += val * val;
48  ct++;
49 }
50 
51 void Stat::add(const Stat& alt)
52 {
53  tot += alt.tot;
54  tot2 += alt.tot2;
55  ct += alt.ct;
56 }
57 
58 double Stat::mean()
59 {
60  compute();
61  return mu;
62 }
63 
65 {
66  compute();
67  return sigma;
68 }
69 
70 double Stat::count()
71 {
72  return ct;
73 }
74 
75 Stat::operator double()
76 {
77  return mean();
78 }
79 
80 void Stat::compute()
81 {
82  if (ct != at) {
83  // ct must be > 0
84  mu = tot / ct;
85  sigma = tot2 / ct - mu * mu;
86  if (sigma < 0) {
87  sigma = 0; // round-off error
88  }
89  sigma = sqrt(sigma);
90  at = ct;
91  }
92 }
93 
94 
96 {
97  totalTime.clear();
98  targetTime.clear();
99 }
100 
102 {
103  totalTime.add(alt.totalTime);
105 }
106 
107 
109 {
110  period.clear();
111 }
112 
113 void RateResult::add(const RateResult& alt)
114 {
115  period.add(alt.period);
116 }
117 
118 
119 Ping::Ping(const char* target)
120 {
121  if (target != nullptr) {
122  setTarget(target);
123  }
124 }
125 
126 bool Ping::setTarget(const char* target)
127 {
128  this->target = target;
129  return true;
130 }
131 
132 
134 {
135  lastConnect.clear();
136  double start = SystemClock::nowSystem();
137  Contact c = NetworkBase::queryName(target);
138  double afterQuery = SystemClock::nowSystem();
139  if (!c.isValid()) {
140  yCError(PING, "Port not found during ping");
141  }
143  rpc.admin = true;
144  rpc.quiet = true;
145  Bottle cmd;
146  Bottle reply;
147  cmd.addVocab(Vocab::encode("ver"));
148  bool ok = NetworkBase::write(c, cmd, reply, rpc);
149  if (!ok) {
150  yCError(PING, "Port did not respond as expected");
151  }
152  double stop = SystemClock::nowSystem();
153  lastConnect.totalTime.add(stop - start);
154  lastConnect.targetTime.add(stop - afterQuery);
155  accumConnect.add(lastConnect);
156 }
157 
159 {
160  long int ping = lround(accumConnect.targetTime.count() + 0.5);
161  if (ping > 0) {
162  yCInfo(PING, "Ping #%ld:\n", lround(accumConnect.targetTime.count() + 0.5));
163  int space = 14;
164  int decimal = 5;
165  yCInfo(PING,
166  " %s connection time (%s with name lookup)\n",
167  renderTime(lastConnect.targetTime.mean(), space, decimal).c_str(),
168  renderTime(lastConnect.totalTime.mean(), space, decimal).c_str());
169  if (accumConnect.totalTime.count() > 1) {
170  yCInfo(PING,
171  " %s +/- %s on average (%s +/- %s with name lookup)\n",
172  renderTime(accumConnect.targetTime.mean(), space, decimal).c_str(),
173  renderTime(accumConnect.targetTime.deviation(), space, decimal).c_str(),
174  renderTime(accumConnect.totalTime.mean(), space, decimal).c_str(),
175  renderTime(accumConnect.totalTime.deviation(), space, decimal).c_str());
176  }
177  }
178 }
179 
180 
181 std::string Ping::renderTime(double t, int space, int decimal)
182 {
183  std::string unit;
184  double times = 1;
185  if (space < 0) {
186  yCError(PING, "Negative space");
187  }
188  if (t >= 1) {
189  unit = "sec";
190  } else if (t > 1e-3) {
191  unit = " ms";
192  times = 1e3;
193  } else if (t > 1e-6) {
194  unit = " us";
195  times = 1e6;
196  } else if (t > 1e-9) {
197  unit = " ns";
198  times = 1e9;
199  }
200  char buf[512];
201  std::snprintf(buf, sizeof(buf), "%.*f%s", decimal, t * times, unit.c_str());
202  return buf;
203 }
204 
205 
206 class PingSampler : public PortReader
207 {
208 public:
209  std::mutex mutex;
210  int ct{0};
211  double lastTime{0};
213 
215  mutex()
216  {
217  }
218 
219  bool read(ConnectionReader& connection) override
220  {
221  double now = SystemClock::nowSystem();
222  Bottle b;
223  bool ok = b.read(connection);
224  if (ok) {
225  mutex.lock();
226  ct++;
227  if (ct > 1) {
228  double dt = now - lastTime;
229  period.add(dt);
230  }
231  lastTime = now;
232  yCInfo(PING,
233  "Period is %g +/- %g (%d)\n",
234  period.mean(),
235  period.deviation(),
236  ct);
237  mutex.unlock();
238  }
239  return ok;
240  }
241 };
242 
244 {
245  Port p;
246  PingSampler sampler;
247  p.setReader(sampler);
248  p.open("...");
249  yCInfo(PING, "Pausing for 5 seconds...\n");
250  NetworkBase::connect(target, p.getName());
252  p.close();
253  yCInfo(PING,
254  "Period is %g +/- %g (%d)\n",
255  sampler.period.mean(),
256  sampler.period.deviation(),
257  sampler.ct);
258 }
259 
261 {
262  lastConnect.clear();
263  accumConnect.clear();
264 }
265 
267 {
268  return lastConnect;
269 }
270 
272 {
273  return accumConnect;
274 }
float t
static bool rpc(const Contact &c, const char *carrier, Bottle &writer, Bottle &reader)
Definition: RosLookup.cpp:22
int ct
Definition: Ping.cpp:210
PingSampler()
Definition: Ping.cpp:214
std::mutex mutex
Definition: Ping.cpp:209
Stat period
Definition: Ping.cpp:212
bool read(ConnectionReader &connection) override
Read this object from a network connection.
Definition: Ping.cpp:219
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
void add(const ConnectResult &alt)
Definition: Ping.cpp:101
An interface for reading from a network connection.
Preferences for how to communicate with a contact.
Definition: ContactStyle.h:27
Represents how to reach a part of a YARP network.
Definition: Contact.h:39
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:301
virtual std::string getName() const
Get name of port.
Definition: Contactable.cpp:17
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition: Network.cpp:685
static Contact queryName(const std::string &name)
Find out information about a registered name.
Definition: Network.cpp:998
static bool write(const Contact &contact, PortWriter &cmd, PortReader &reply, bool admin=false, bool quiet=false, double timeout=-1)
Send a single command to a port and await a single response.
Definition: Network.cpp:1229
void sample()
Definition: Ping.cpp:243
bool setTarget(const char *target)
Definition: Ping.cpp:126
Ping(const char *target=nullptr)
Definition: Ping.cpp:119
void report()
Definition: Ping.cpp:158
void clear()
Definition: Ping.cpp:260
static std::string renderTime(double t, int space, int decimal)
Definition: Ping.cpp:181
ConnectResult getAverageConnect()
Definition: Ping.cpp:271
ConnectResult getLastConnect()
Definition: Ping.cpp:266
void connect()
Definition: Ping.cpp:133
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition: PortReader.h:28
A mini-server for network communication.
Definition: Port.h:50
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition: Port.cpp:505
void close() override
Stop port activity.
Definition: Port.cpp:357
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:82
void add(const RateResult &alt)
Definition: Ping.cpp:113
void add(double val)
Definition: Ping.cpp:44
void clear()
Definition: Ping.cpp:34
double mean()
Definition: Ping.cpp:58
double count()
Definition: Ping.cpp:70
double deviation()
Definition: Ping.cpp:64
static double nowSystem()
Definition: SystemClock.cpp:37
static void delaySystem(double seconds)
Definition: SystemClock.cpp:32
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:37
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
NetInt32 encode(const std::string &str)
Convert a string into a vocabulary identifier.
Definition: Vocab.cpp:14
An interface to the operating system, including Port based communication.