TimeStamp.cc
Go to the documentation of this file.
1 
42 #include "TimeStamp.hh"
43 
44 #ifndef WIN32
45 #include <sys/time.h>
46 #endif
47 #include <time.h>
48 
49 namespace crl {
50 namespace multisense {
51 namespace details {
52 namespace utility {
53 
54 
55 // Initialize static routines.
56 
58 
59 #if defined (WIN32)
60 
61 //
62 // The FILETIME structure in Windows measures time in 100-nanosecond intervals
63 // since 1601-Jan-01. The timeval structure measures time in second intervals
64 // since 1970-Jan-01. This function computes the number of seconds (as a double)
65 // that we need to apply as an offset to ensure that clock times are all tracked
66 // from the same epoch.
67 static ULARGE_INTEGER initOffsetSecondsSince1970 ()
68 {
69  SYSTEMTIME epochTimeAsSystemTime = { 1970, 1, 0, 1, 0, 0, 0, 0 };
70  FILETIME epochTimeAsFileTime;
71  SystemTimeToFileTime (&epochTimeAsSystemTime, &epochTimeAsFileTime);
72 
73  ULARGE_INTEGER epochTime;
74  epochTime.LowPart = epochTimeAsFileTime.dwLowDateTime;
75  epochTime.HighPart = epochTimeAsFileTime.dwHighDateTime;
76 
77  return epochTime;
78 }
79 
80 ULARGE_INTEGER TimeStamp::offsetSecondsSince1970 = initOffsetSecondsSince1970 ();
81 
82 #endif
83 
84 /*
85  * Constructor. Empty. We rely on the getter methods to do
86  * things that are more useful.
87  */
89 {
90  this->time.tv_sec = 0;
91  this->time.tv_usec = 0;
92 }
93 
94 /*
95  * Constructor. Initializes with the specified timestamp value.
96  */
97 TimeStamp::TimeStamp(struct timeval& value)
98 {
99  this->set(value);
100 }
101 
102 /*
103  * Cosntructor. Initializes with the specified timestamp value.
104  */
105 TimeStamp::TimeStamp(double value)
106 {
107  this->time.tv_sec = (int) value;
108  this->time.tv_usec = (int) ((value - this->time.tv_sec) * 1000000);
109 }
110 
111 /*
112  * Sets this timestamp equal to the timestamp specified.
113  */
114 void TimeStamp::set(struct timeval& value)
115 {
116  this->time.tv_sec = value.tv_sec;
117  this->time.tv_usec = value.tv_usec;
118 }
119 
120 /*
121  * Sets the time, for time synchronization. This will report the local clock when
122  * the PPS event occurred, and the remote clock when the PPS event occurred.
123  *
124  * When you use the routine 'getCurrentTime()', it will then return a timestamp
125  * that is time-synchronized with the remote system.
126  */
128 {
129  setTimeAtPps(local.time, remote.time);
130 }
131 
132 /*
133  * Sets the time, for time synchronization. This will report the local clock when
134  * the PPS event occurred, and the remote clock when the PPS event occurred.
135  *
136  * When you use the routine 'getCurrentTime()', it will then return a timestamp
137  * that is time-synchronized with the remote system.
138  */
139 void TimeStamp::setTimeAtPps(struct timeval& local, struct timeval& remote)
140 {
141  //
142  // To make things atomic, we are somewhat in trouble. To make things lock-free,
143  // we are going to do all of the math as doubles. Convert the above timestamps
144  // to doubles.
145  //
146 
147  double localTimeAtPps = local.tv_sec + (local.tv_usec / 1000000.0);
148  double remoteTimeAtPps = remote.tv_sec + (remote.tv_usec / 1000000.0);
149 
150  //
151  // Store the offset between the two as a static variable.
152  //
153 
154  timeSynchronizationOffset = remoteTimeAtPps - localTimeAtPps;
155 }
156 
157 /*
158  * Returns the offset from the remote clock to the local clock. Add this to the
159  * time returned by a standard time call to have a synchronized time. Notice that
160  * this is already applied to anything using TimeStamps normally.
161  */
163 {
165 }
166 
167 #ifndef SENSORPOD_FIRMWARE
168 
169 /*
170  * This routine will get the current time (as gettimeofday()) and
171  * store it off. It is the normal way of initializing time. Notice
172  * that there may be large time skips when you call this routine, due
173  * to time synchronization jumps.
174  *
175  * Notice that the timestamp returned by this object *is* atomic. It
176  * will not change, even if time synchronization skews things.
177  */
179 {
180  //
181  // Create a new timestamp object and fill it in with
182  // the current time of day.
183  //
184 
186 
187 #if defined (WIN32)
188 
189  // gettimeofday does not exist on Windows
190  FILETIME currentTimeAsFileTime;
191  GetSystemTimeAsFileTime (&currentTimeAsFileTime);
192 
193  ULARGE_INTEGER currentTimeAsLargeInteger;
194  currentTimeAsLargeInteger.LowPart = currentTimeAsFileTime.dwLowDateTime;
195  currentTimeAsLargeInteger.HighPart = currentTimeAsFileTime.dwHighDateTime;
196  currentTimeAsLargeInteger.QuadPart -= offsetSecondsSince1970.QuadPart;
197 
198  timeStamp.time.tv_sec = static_cast<long> (currentTimeAsLargeInteger.QuadPart / 10000000);
199  timeStamp.time.tv_usec = static_cast<long> ((currentTimeAsLargeInteger.QuadPart - timeStamp.time.tv_sec * 10000000) / 10);
200 
201 #else
202  gettimeofday(&timeStamp.time, 0);
203 #endif
204 
205  //
206  // Transform it into a double... Notice that this (quite handily)
207  // removes all precision up to the 100-nanosecond mark, making carrying
208  // times around as timevals fairly pointless. We do this to apply the
209  // time synchronization offset, lockless-ly.
210  //
211  // It's probably that this is pointless, and we should add a lock
212  // in the future.
213  //
214 
215  double currentTime = (double) timeStamp;
216 
217  currentTime += timeSynchronizationOffset;
218 
219  timeStamp = currentTime;
220 
221  //
222  // Return the final timestamp.
223  //
224 
225  return timeStamp;
226 }
227 
228 #endif // SENSORPOD_FIRMWARE
229 
230 /*
231  * Returns the seconds portion of the timestamp.
232  */
233 uint32_t TimeStamp::getSeconds() const
234 {
235  return this->time.tv_sec;
236 }
237 
238 /*
239  * Returns the microseconds portion of the timestamp.
240  */
242 {
243  return this->time.tv_usec;
244 }
245 
246 /*
247  * Returns the stored time as if it was a double. This will be seconds since 1970.
248  * The time will be accurate to the (roughly) 100-nanosecond mark.
249  */
250 TimeStamp::operator double() const
251 {
252  return this->time.tv_sec + (this->time.tv_usec / 1000000.0);
253 }
254 
255 /*
256  * Sets the stored time from the seconds value given.
257  */
258 TimeStamp& TimeStamp::operator=(double timeStamp)
259 {
260  this->time.tv_sec = ((unsigned long) timeStamp);
261  this->time.tv_usec = ((unsigned long) ((timeStamp - this->time.tv_sec) * 1000000));
262 
263  // This call avoids having negative microseconds if the input
264  // argument is less than zero and non-integral.
265  this->normalize();
266 
267  return *this;
268 }
269 
270 
272 {
273  this->time.tv_sec += other.time.tv_sec;
274  this->time.tv_usec += other.time.tv_usec;
275  this->normalize();
276  return *this;
277 }
278 
279 
281 {
282  this->time.tv_sec -= other.time.tv_sec;
283  this->time.tv_usec -= other.time.tv_usec;
284  this->normalize();
285  return *this;
286 }
287 
288 
290 {
291  while(this->time.tv_usec < 0) {
292  this->time.tv_usec += 1000000;
293  this->time.tv_sec -= 1;
294  }
295 
296  while(this->time.tv_usec >= 1000000) {
297  this->time.tv_usec -= 1000000;
298  this->time.tv_sec += 1;
299  }
300 }
301 
302 
303 //
304 // Arithmetic operators are mostly handled by implicit conversion to
305 // and from double.
306 //
307 
308 // TimeStamp operator +(TimeStamp const& arg0, TimeStamp const& arg1)
309 // {
310 // TimeStamp result = arg0;
311 // result += arg1;
312 // return result;
313 // }
314 
315 
316 // TimeStamp operator -(TimeStamp const& arg0, TimeStamp const& arg1)
317 // {
318 // TimeStamp result = arg0;
319 // result -= arg1;
320 // return result;
321 // }
322 
323 }}}} // namespaces
TimeStamp & operator=(double timeStamp)
Definition: TimeStamp.cc:258
ros::Time * timeStamp(M &m)
TimeStamp & operator+=(TimeStamp const &other)
Definition: TimeStamp.cc:271
TimeStamp & operator-=(TimeStamp const &other)
Definition: TimeStamp.cc:280
Definition: channel.cc:56
static void setTimeAtPps(TimeStamp &local, TimeStamp &remote)
Definition: TimeStamp.cc:127


multisense_lib
Author(s):
autogenerated on Sat Apr 6 2019 02:16:46