Package roslib :: Module rostime

Source Code for Module roslib.rostime

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2008, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: rostime.py 11746 2010-10-25 03:35:03Z kwc $ 
 34   
 35  """ 
 36  ROS Time representation, including Duration 
 37  """ 
 38   
 39  import itertools 
 40  import time 
41 42 -def _canon(secs, nsecs):
43 #canonical form: nsecs is always positive, nsecs < 1 second 44 while nsecs >= 1000000000: 45 secs += 1 46 nsecs -= 1000000000 47 while nsecs < 0: 48 secs -= 1 49 nsecs += 1000000000 50 return secs,nsecs
51 52 import warnings
53 -def deprecated(func):
54 """This is a decorator which can be used to mark functions 55 as deprecated. It will result in a warning being emmitted 56 when the function is used.""" 57 def newFunc(*args, **kwargs): 58 warnings.warn("Call to deprecated function %s." % func.__name__, 59 category=DeprecationWarning, stacklevel=2) 60 return func(*args, **kwargs)
61 newFunc.__name__ = func.__name__ 62 newFunc.__doc__ = func.__doc__ 63 newFunc.__dict__.update(func.__dict__) 64 return newFunc 65
66 -class TVal(object):
67 """ 68 Base class of L{Time} and L{Duration} representations. Representation 69 is secs+nanoseconds since epoch. 70 """ 71 72 __slots__ = ['secs', 'nsecs']
73 - def __init__(self, secs=0, nsecs=0):
74 """ 75 @param secs: seconds. If secs is a float, then nsecs must not be set or 0 76 @type secs: int/float 77 @param nsecs: nanoseconds 78 @type nsecs: int 79 """ 80 if type(secs) != int: 81 # float secs constructor 82 if nsecs != 0: 83 raise ValueError("if secs is a float, nsecs cannot be set") 84 float_secs = secs 85 secs = int(float_secs) 86 nsecs = int((float_secs - secs) * 1000000000) 87 88 self.secs, self.nsecs = _canon(secs, nsecs)
89
90 - def is_zero(self):
91 """ 92 @return: True if time is zero (secs and nsecs are zero) 93 @rtype: bool 94 """ 95 return self.secs == 0 and self.nsecs == 0
96
97 - def set(self, secs, nsecs):
98 """ 99 Set time using separate secs and nsecs values 100 101 @param secs: seconds since epoch 102 @type secs: int 103 @param nsecs: nanoseconds since seconds 104 @type nsecs: int 105 """ 106 self.secs = secs 107 self.nsecs = nsecs
108
109 - def canon(self):
110 """ 111 Canonicalize the field representation in this instance. should 112 only be used when manually setting secs/nsecs slot values, as 113 in deserialization. 114 """ 115 self.secs, self.nsecs = _canon(self.secs, self.nsecs)
116
117 - def to_sec(self):
118 """ 119 @return: time as float seconds (same as time.time() representation) 120 @rtype: float 121 """ 122 return float(self.secs) + float(self.nsecs) / 1e9
123
124 - def to_nsec(self):
125 """ 126 @return: time as nanoseconds 127 @rtype: long 128 """ 129 return self.secs * long(1e9) + self.nsecs
130
131 - def __hash__(self):
132 """ 133 Time values are hashable. Time values with identical fields have the same hash. 134 """ 135 return ("%s.%s"%(self.secs, self.nsecs)) .__hash__()
136
137 - def __str__(self):
138 return str(self.to_nsec())
139
140 - def __repr__(self):
141 return "rostime.TVal[%d]"%self.to_nsec()
142
143 - def __nonzero__(self):
144 """ 145 Check if time value is zero 146 """ 147 return self.secs or self.nsecs
148
149 - def __lt__(self, other):
150 """ 151 < test for time values 152 """ 153 try: 154 return self.__cmp__(other) < 0 155 except TypeError: 156 return NotImplemented
157 - def __le__(self, other):
158 """ 159 <= test for time values 160 """ 161 try: 162 return self.__cmp__(other) <= 0 163 except TypeError: 164 return NotImplemented
165 - def __gt__(self, other):
166 """ 167 > test for time values 168 """ 169 try: 170 return self.__cmp__(other) > 0 171 except TypeError: 172 return NotImplemented
173 - def __ge__(self, other):
174 """ 175 >= test for time values 176 """ 177 try: 178 return self.__cmp__(other) >= 0 179 except TypeError: 180 return NotImplemented
181 - def __ne__(self, other):
182 return not self.__eq__(other)
183 - def __cmp__(self, other):
184 if not isinstance(other, TVal): 185 raise TypeError("Cannot compare to non-TVal") 186 nanos = self.to_nsec() - other.to_nsec() 187 if nanos > 0: 188 return 1 189 if nanos == 0: 190 return 0 191 return -1
192 - def __eq__(self, other):
193 if not isinstance(other, TVal): 194 return False 195 return self.to_nsec() == other.to_nsec()
196
197 -class Time(TVal):
198 """ 199 Time contains the ROS-wide 'time' primitive representation, which 200 consists of two integers: seconds since epoch and nanoseconds since 201 seconds. Time instances are mutable. 202 """ 203 __slots__ = ['secs', 'nsecs']
204 - def __init__(self, secs=0, nsecs=0):
205 """ 206 Constructor: secs and nsecs are integers. You may prefer to use the static L{from_sec()} factory 207 method instead. 208 209 @param secs: seconds since epoch 210 @type secs: int 211 @param nsecs: nanoseconds since seconds (since epoch) 212 @type nsecs: int 213 """ 214 super(Time, self).__init__(secs, nsecs) 215 if self.secs < 0: 216 raise TypeError("time values must be positive")
217
218 - def __getstate__(self):
219 """ 220 support for Python pickling 221 """ 222 return [self.secs, self.nsecs]
223
224 - def __setstate__(self, state):
225 """ 226 support for Python pickling 227 """ 228 self.secs, self.nsecs = state
229 230 @deprecated
231 - def from_seconds(float_secs):
232 """ 233 Use from_sec() instead. This is retained for backwards compatibility. 234 235 @param float_secs: time value in time.time() format 236 @type float_secs: float 237 @return: Time instance for specified time 238 @rtype: L{Time} 239 """ 240 return Time.from_sec(float_secs)
241
242 - def from_sec(float_secs):
243 """ 244 Create new Time instance using time.time() value (float 245 seconds) 246 247 @param float_secs: time value in time.time() format 248 @type float_secs: float 249 @return: Time instance for specified time 250 @rtype: L{Time} 251 """ 252 secs = int(float_secs) 253 nsecs = int((float_secs - secs) * 1000000000) 254 return Time(secs, nsecs)
255 256 from_seconds = staticmethod(from_seconds) 257 from_sec = staticmethod(from_sec) 258
259 - def to_time(self):
260 """ 261 Get Time in time.time() format. alias of L{to_sec()} 262 263 @return: time in floating point secs (time.time() format) 264 @rtype: float 265 """ 266 return self.to_sec()
267
268 - def __repr__(self):
269 return "rostime.Time[%d]"%self.to_nsec()
270
271 - def __add__(self, other):
272 """ 273 Add duration to this time 274 275 @param other: duration 276 @type other: L{Duration} 277 """ 278 if not isinstance(other, Duration): 279 return NotImplemented 280 return Time(self.secs + other.secs, self.nsecs + other.nsecs)
281
282 - def __sub__(self, other):
283 """ 284 Subtract time or duration from this time 285 @param other: duration 286 @type other: L{Duration}/L{Time} 287 @return: L{Duration} if other is a L{Time}, L{Time} if other is a L{Duration} 288 """ 289 if isinstance(other, Time): 290 return Duration(self.secs - other.secs, self.nsecs - other.nsecs) 291 elif isinstance(other, Duration): 292 return Time(self.secs - other.secs, self.nsecs - other.nsecs) 293 else: 294 return NotImplemented
295
296 - def __cmp__(self, other):
297 """ 298 Compare to another time 299 @param other: Time 300 @type other: L{Time} 301 """ 302 if not isinstance(other, Time): 303 raise TypeError("cannot compare to non-Time") 304 nanos = self.to_nsec() - other.to_nsec() 305 if nanos > 0: 306 return 1 307 if nanos == 0: 308 return 0 309 return -1
310
311 - def __eq__(self, other):
312 """ 313 Equals test for Time. Comparison assumes that both time 314 instances are in canonical representation; only compares fields. 315 316 @param other: Time 317 @type other: L{Time} 318 """ 319 if not isinstance(other, Time): 320 return False 321 return self.secs == other.secs and self.nsecs == other.nsecs
322
323 -class Duration(TVal):
324 """ 325 Duration represents the ROS 'duration' primitive, which consists 326 of two integers: seconds and nanoseconds. The Duration class 327 allows you to add and subtract Duration instances, including 328 adding and subtracting from L{Time} instances. 329 """ 330 __slots__ = ['secs', 'nsecs']
331 - def __init__(self, secs=0, nsecs=0):
332 """ 333 Create new Duration instance. secs and nsecs are integers and correspond to the ROS 'duration' primitive. 334 335 @param secs: seconds 336 @type secs: int 337 @param nsecs: nanoseconds 338 @type nsecs: int 339 """ 340 super(Duration, self).__init__(secs, nsecs)
341
342 - def __getstate__(self):
343 """ 344 support for Python pickling 345 """ 346 return [self.secs, self.nsecs]
347
348 - def __setstate__(self, state):
349 """ 350 support for Python pickling 351 """ 352 self.secs, self.nsecs = state
353
354 - def __repr__(self):
355 return "rostime.Duration[%d]"%self.to_nsec()
356
357 - def from_sec(float_seconds):
358 """ 359 Create new Duration instance from float seconds format. 360 361 @param float_seconds: time value in specified as float seconds 362 @type float_seconds: float 363 @return: Duration instance for specified float_seconds 364 @rtype: Duration 365 """ 366 secs = int(float_seconds) 367 nsecs = int((float_seconds - secs) * 1000000000) 368 return Duration(secs, nsecs)
369 370 from_sec = staticmethod(from_sec) 371
372 - def __neg__(self):
373 """ 374 @return: Negative value of this duration 375 @rtype: L{Duration} 376 """ 377 return Duration(-self.secs, -self.nsecs)
378 - def __abs__(self):
379 """ 380 Absolute value of this duration 381 @return: positive duration 382 @rtype: L{Duration} 383 """ 384 if self.secs > 0: 385 return self 386 return self.__neg__()
387
388 - def __add__(self, other):
389 """ 390 Add duration to this duration, or this duration to a time, creating a new time value as a result. 391 @param other: duration or time 392 @type other: L{Duration}/L{Time} 393 @return: L{Duration} if other is a L{Duration}, L{Time} if other is a L{Time} 394 """ 395 if isinstance(other, Time): 396 return other.__add__(self) 397 elif isinstance(other, Duration): 398 return Duration(self.secs+other.secs, self.nsecs+other.nsecs) 399 else: 400 return NotImplemented
401 - def __sub__(self, other):
402 """ 403 Subtract duration from this duration, returning a new duration 404 @param other: duration 405 @type other: L{Duration} 406 @return: L{Duration} 407 """ 408 if not isinstance(other, Duration): 409 return NotImplemented 410 return Duration(self.secs-other.secs, self.nsecs-other.nsecs)
411
412 - def __mul__(self, val):
413 """ 414 Multiply this duration by an integer or float 415 @param val: multiplication factor 416 @type val: int/float 417 @return: Duration multiplied by val 418 @rtype: L{Duration} 419 """ 420 t = type(val) 421 if t in (int, long): 422 return Duration(self.secs * val, self.nsecs * val) 423 elif t == float: 424 return Duration.from_sec(self.to_sec() * val) 425 else: 426 return NotImplemented
427
428 - def __floordiv__(self, val):
429 """ 430 Floor divide this duration by an integer or float 431 @param val: division factor 432 @type val: int/float 433 @return: Duration multiplied by val 434 @rtype: L{Duration} 435 """ 436 t = type(val) 437 if t in (int, long): 438 return Duration(self.secs // val, self.nsecs // val) 439 elif t == float: 440 return Duration.from_sec(self.to_sec() // val) 441 else: 442 return NotImplemented
443
444 - def __div__(self, val):
445 """ 446 Divide this duration by an integer or float 447 @param val: division factor 448 @type val: int/float 449 @return: Duration multiplied by val 450 @rtype: L{Duration} 451 """ 452 # unlike __floordiv__, this uses true div for float arg 453 t = type(val) 454 if t in (int, long): 455 return Duration(self.secs // val, self.nsecs // val) 456 elif t == float: 457 return Duration.from_sec(self.to_sec() / val) 458 else: 459 return NotImplemented
460
461 - def __truediv__(self, val):
462 """ 463 Divide this duration by an integer or float 464 @param val: division factor 465 @type val: int/float 466 @return: Duration multiplied by val 467 @rtype: L{Duration} 468 """ 469 t = type(val) 470 if t in (int, long): 471 return Duration(self.secs / val, self.nsecs / val) 472 elif t == float: 473 return Duration.from_sec(self.to_sec() / val) 474 else: 475 return NotImplemented
476
477 - def __cmp__(self, other):
478 if not isinstance(other, Duration): 479 raise TypeError("Cannot compare to non-Duration") 480 nanos = self.to_nsec() - other.to_nsec() 481 if nanos > 0: 482 return 1 483 if nanos == 0: 484 return 0 485 return -1
486
487 - def __eq__(self, other):
488 if not isinstance(other, Duration): 489 return False 490 return self.secs == other.secs and self.nsecs == other.nsecs
491