Hekateros  3.4.3
RoadNarrows Robotics Robot Arm Project
hekUtils.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Hekateros
4 //
5 // Library: libhekateros
6 //
7 // File: hekUtils.cxx
8 //
9 //
10 /*! \file
11  *
12  * $LastChangedDate: 2015-04-23 15:45:00 -0600 (Thu, 23 Apr 2015) $
13  * $Rev: 3956 $
14  *
15  * \brief Hekateros utilities.
16  *
17  * \author Daniel Packard (daniel@roadnarrows.com)
18  * \author Robin Knight (robin.knight@roadnarrows.com)
19  *
20  * \copyright
21  * \h_copy 2012-2017. RoadNarrows LLC.\n
22  * http://www.roadnarrows.com\n
23  * All Rights Reserved
24  */
25 /*
26  * @EulaBegin@
27  *
28  * Unless otherwise stated explicitly, all materials contained are copyrighted
29  * and may not be used without RoadNarrows LLC's written consent,
30  * except as provided in these terms and conditions or in the copyright
31  * notice (documents and software) or other proprietary notice provided with
32  * the relevant materials.
33  *
34  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
35  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
36  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
37  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
38  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
39  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
42  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
43  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
44  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
45  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46  *
47  * @EulaEnd@
48  */
49 ////////////////////////////////////////////////////////////////////////////////
50 
51 
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <sys/time.h>
55 #include <time.h>
56 #include <fcntl.h>
57 #include <unistd.h>
58 #include <libgen.h>
59 #include <stdio.h>
60 #include <errno.h>
61 
62 #include <string>
63 #include <sstream>
64 #include <vector>
65 
66 #include "rnr/rnrconfig.h"
67 #include "rnr/log.h"
68 
69 #include "Hekateros/hekateros.h"
70 #include "Hekateros/hekUtils.h"
71 
72 using namespace std;
73 
74 
75 //------------------------------------------------------------------------------
76 // Private Interface
77 //------------------------------------------------------------------------------
78 
79 /*!
80  * \ingroup libhek
81  * \brief \h_hek Error Code String Table.
82  *
83  * Table is indexed by \h_hek error codes (see \ref hek_ecodes). Keep
84  * in sync.
85  */
86 static const char *EcodeStrTbl[] =
87 {
88  "Ok", ///< [HEK_OK]
89 
90  "Error", ///< [HEK_ECODE_GEN]
91  "System error", ///< [HEK_ECODE_SYS]
92  "Internal error", ///< [HEK_ECODE_INTERNAL]
93  "Bad value", ///< [HEK_ECODE_BAD_VAL]
94  "Too big", ///< [HEK_ECODE_TOO_BIG]
95  "Too small", ///< [HEK_ECODE_TOO_SMALL]
96  "Value out-of-range", ///< [HEK_ECODE_RANGE]
97  "Invalid operation", ///< [HEK_ECODE_BAD_OP]
98  "Operation timed out", ///< [HEK_ECODE_TIMEDOUT]
99  "Device not found", ///< [HEK_ECODE_NO_DEV]
100  "No resource available", ///< [HEK_ECODE_NO_RSRC]
101  "Resource busy", ///< [HEK_ECODE_BUSY]
102  "Cannot execute", ///< [HEK_ECODE_NO_EXEC]
103  "Permissions denied", ///< [HEK_ECODE_PERM]
104  "Dynamixel chain or servo error", ///< [HEK_ECODE_DYNA]
105  "Video error", ///< [HEK_ECODE_VIDEO]
106  "Bad format", ///< [HEK_ECODE_FORMAT]
107  "BotSense error", ///< [HEK_ECODE_BOTSENSE]
108  "File not found", ///< [HEK_ECODE_NO_FILE]
109  "XML error", ///< [HEK_ECODE_XML]
110  "Robot is in an alarmed state", ///< [HEK_ECODE_ALARMED]
111  "Operation interrupted", ///< [HEK_ECODE_INTR]
112  "Robotic link(s) movement obstructed", ///< [HEK_ECODE_COLLISION]
113  "Robot emergency stopped", ///< [HEK_ECODE_ESTOP]
114 
115  "Invalid error code" ///< [HEK_ECODE_BADEC]
116 };
117 
118 
119 //------------------------------------------------------------------------------
120 // Public Interface
121 //------------------------------------------------------------------------------
122 
123 const char *hekateros::getStrError(const int ecode)
124 {
125  int ec = ecode >= 0 ? ecode : -ecode;
126 
127  if( ec >= arraysize(EcodeStrTbl) )
128  {
129  ec = HEK_ECODE_BADEC;
130  }
131 
132  return EcodeStrTbl[ec];
133 }
134 
135 uint_t hekateros::strToVersion(const string &str)
136 {
137  int nMajor = 0;
138  int nMinor = 0;
139  int nRevision = 0;
140 
141  sscanf(str.c_str(), "%d.%d.%d", &nMajor, &nMinor, &nRevision);
142 
143  return HEK_VERSION(nMajor, nMinor, nRevision);
144 }
145 
146 bool hekateros::operator<(const struct timeval& lhs, const struct timeval& rhs)
147 {
148  if( lhs.tv_sec < rhs.tv_sec )
149  {
150  return true;
151  }
152  else if( (lhs.tv_sec == rhs.tv_sec) && (lhs.tv_usec < rhs.tv_usec) )
153  {
154  return true;
155  }
156  else
157  {
158  return false;
159  }
160 }
161 
162 bool hekateros::operator==(const struct timeval& lhs, const struct timeval& rhs)
163 {
164  return (lhs.tv_sec == rhs.tv_sec) && (lhs.tv_usec == rhs.tv_usec)?
165  true: false;
166 }
167 
168 bool hekateros::operator>(const struct timeval& lhs, const struct timeval& rhs)
169 {
170  return !((lhs < rhs) || (lhs == rhs));
171 }
172 
173 struct timeval hekateros::operator+(const struct timeval& op1,
174  const struct timeval& op2)
175 {
176  struct timeval sum = op1;
177 
178  sum.tv_sec += op2.tv_sec;
179  sum.tv_usec += op2.tv_usec;
180 
181  if( sum.tv_usec > MILLION )
182  {
183  ++sum.tv_sec;
184  sum.tv_usec -= MILLION;
185  }
186 
187  return sum;
188 }
189 
190 struct timeval hekateros::operator-(const struct timeval& op1,
191  const struct timeval& op2)
192 {
193  struct timeval diff;
194 
195  diff.tv_sec = op1.tv_sec - op2.tv_sec;
196 
197  if( op1.tv_usec >= op2.tv_usec)
198  {
199  diff.tv_usec = op1.tv_usec - op2.tv_usec;
200  }
201  else
202  {
203  --diff.tv_sec;
204  diff.tv_usec = MILLION + op1.tv_usec - op2.tv_usec;
205  }
206 
207  return diff;
208 }
209 
210 long hekateros::dt_usec(struct timeval& t1, struct timeval& t0)
211 {
212  struct timeval dt = t1 - t0;
213 
214  return (long)dt.tv_sec * MILLION + (long)dt.tv_usec;
215 }
216 
217 double hekateros::dt(struct timeval& t1, struct timeval& t0)
218 {
219  if( t0 < t1 )
220  {
221  return (double)dt_usec(t1, t0) / (double)MILLION;
222  }
223  else
224  {
225  return -(double)dt_usec(t0, t1) / (double)MILLION;
226  }
227 }
228 
229 bool hekateros::operator<(const struct timespec& lhs,
230  const struct timespec& rhs)
231 {
232  if( lhs.tv_sec < rhs.tv_sec )
233  {
234  return true;
235  }
236  else if( (lhs.tv_sec == rhs.tv_sec) && (lhs.tv_nsec < rhs.tv_nsec) )
237  {
238  return true;
239  }
240  else
241  {
242  return false;
243  }
244 }
245 
246 bool hekateros::operator==(const struct timespec& lhs,
247  const struct timespec& rhs)
248 {
249  return (lhs.tv_sec == rhs.tv_sec) && (lhs.tv_nsec == rhs.tv_nsec)?
250  true: false;
251 }
252 
253 bool hekateros::operator>(const struct timespec& lhs,
254  const struct timespec& rhs)
255 {
256  return !((lhs < rhs) || (lhs == rhs));
257 }
258 
259 struct timespec hekateros::operator+(const struct timespec& op1,
260  const struct timespec& op2)
261 {
262  struct timespec sum = op1;
263 
264  sum.tv_sec += op2.tv_sec;
265  sum.tv_nsec += op2.tv_nsec;
266 
267  if( sum.tv_nsec > BILLION )
268  {
269  ++sum.tv_sec;
270  sum.tv_nsec -= BILLION;
271  }
272 
273  return sum;
274 }
275 
276 struct timespec hekateros::operator-(const struct timespec& op1,
277  const struct timespec& op2)
278 {
279  struct timespec diff;
280 
281  diff.tv_sec = op1.tv_sec - op2.tv_sec;
282 
283  if( op1.tv_nsec >= op2.tv_nsec)
284  {
285  diff.tv_nsec = op1.tv_nsec - op2.tv_nsec;
286  }
287  else
288  {
289  --diff.tv_sec;
290  diff.tv_nsec = BILLION + op1.tv_nsec - op2.tv_nsec;
291  }
292 
293  return diff;
294 }
295 
296 long long hekateros::dt_nsec(struct timespec& t1, struct timespec& t0)
297 {
298  struct timespec dt = t1 - t0;
299 
300  return (long long)dt.tv_sec * BILLION + (long long)dt.tv_nsec;
301 }
302 
303 double hekateros::dt(struct timespec& t1, struct timespec& t0)
304 {
305  if( t0 < t1 )
306  {
307  return (double)dt_nsec(t1, t0) / (double)BILLION;
308  }
309  else
310  {
311  return -(double)dt_nsec(t0, t1) / (double)BILLION;
312  }
313 }
314 
315 string hekateros::getRealDeviceName(const string &strDevName)
316 {
317  char buf[MAX_PATH+1];
318  ssize_t len;
319 
320  //
321  // Symbolic link.
322  //
323  if( (len = readlink(strDevName.c_str(), buf, MAX_PATH)) > 0 )
324  {
325  buf[len] = 0;
326 
327  // absollute path
328  if( buf[0] == '/' )
329  {
330  string strRealDevName(buf);
331  return strRealDevName;
332  }
333 
334  // relative path
335  else
336  {
337  char s[strDevName.size()+1];
338  stringstream ss;
339 
340  strcpy(s, strDevName.c_str());
341 
342  char *sDirName = dirname(s);
343 
344  ss << sDirName << "/" << buf;
345 
346  return ss.str();
347  }
348  }
349 
350  //
351  // Real device.
352  //
353  else
354  {
355  return strDevName;
356  }
357 }
358 
359 vector<string> &hekateros::split(const string &s,
360  char delim,
361  vector<string> &elems)
362 {
363  stringstream ss(s);
364  string item;
365 
366  while( getline(ss, item, delim) )
367  {
368  elems.push_back(item);
369  }
370  return elems;
371 }
372 
373 vector<string> hekateros::split(const string &s, char delim)
374 {
375  vector<string> elems;
376 
377  split(s, delim, elems);
378 
379  return elems;
380 }
bool operator>(const struct timeval &lhs, const struct timeval &rhs)
Compare operator to test if left hand side time is later than the right hand side time...
bool operator<(const struct timeval &lhs, const struct timeval &rhs)
Compare operator to test if left hand side time is earlier than the right hand side time...
double dt(struct timeval &t1, struct timeval &t0)
Calculate delta time.
static const char * EcodeStrTbl[]
<b><i>Hekateros</i></b> Error Code String Table.
Definition: hekUtils.cxx:86
const char * getStrError(const int ecode)
Get the error string describing the <b><i>Hekateros</i></b> error code.
bool operator==(const struct timeval &lhs, const struct timeval &rhs)
Compare operator to test if left hand side time equals the right hand side time.
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Split string at the delimiter character.
Top-level package include file.
uint_t strToVersion(const std::string &str)
Convert version dotted string to integer equivalent.
std::string getRealDeviceName(const std::string &strDevName)
Get real device name.
#define HEK_VERSION(major, minor, revision)
Convert version triplet to integer equivalent.
Definition: hekateros.h:185
Hekateros common utilities.
long long dt_nsec(struct timespec &t1, struct timespec &t0)
Calculate delta time in nanoseconds.
The <b><i>Hekateros</i></b> namespace encapsulates all <b><i>Hekateros</i></b> related constructs...
Definition: hekateros.h:56
long dt_usec(struct timeval &t1, struct timeval &t0)
Calculate delta time in microseconds.