Source code for morse.core.morse_time

"""
This module deals with the time management in Morse, providing several
possible implementations.

At the moment, it provides two implementations:
    - best effort (i.e. try to simulate at real-time, by dropping
      frame). The simulation is less acurate, because the physical steps
      are not really constant.
    - fixed simulation step. Compute all physical / logical step. The
      simulation will be more precise, but the simulation time will
      differ from computer clock time.
"""

import logging
logger = logging.getLogger("morse." + __name__)
import time
from morse.core import blenderapi
from morse.helpers.statistics import Stats

[docs]class BestEffortStrategy: def __init__ (self): self.time = time.time() self._stat_jitter = Stats() self._stat_nb_frame = Stats() self._time_frame = 0.0 self._last_time = 0.0 self._nb_frame = 0 logger.info('Morse configured in Best Effort Mode')
[docs] def update (self): self.time = time.time() self._update_statistics()
[docs] def name(self): return 'Best Effort'
@property def mean(self): return self._stat_jitter.mean
[docs] def statistics(self): return { "mean_time" : self._stat_jitter.mean, "variance_time": self._stat_jitter.variance, "mean_frame_by_sec": self._stat_nb_frame.mean, "variance_frame_by_sec": self._stat_nb_frame.variance }
def _update_statistics(self): if self._last_time == 0.0: self._last_time = self.time else: ds = self.time - self._last_time self._last_time = self.time self._stat_jitter.update(ds) if self._nb_frame == 0: self._time_frame = self.time self._nb_frame = 1 else: if self.time - self._time_frame > 1.0: self._stat_nb_frame.update(self._nb_frame) self._nb_frame = 0 else: self._nb_frame = self._nb_frame + 1
[docs]class FixedSimulationStepStrategy: def __init__ (self): self.time = time.time() self._incr = 1.0 / blenderapi.getfrequency() self._stat_jitter = Stats() self._last_time = 0.0 logger.info('Morse configured in Fixed Simulation Step Mode with ' 'time step of %f sec ( 1.0 / %d)' % (self._incr, blenderapi.getfrequency()))
[docs] def update (self): self.time = self.time + self._incr self._update_statistics()
[docs] def name (self): return 'Fixed Simulation Step'
@property def mean(self): return self._incr
[docs] def statistics (self): return { "mean_time" : self._stat_jitter.mean, "variance_time": self._stat_jitter.variance, "diff_real_time": self.time - time.time() }
def _update_statistics(self): if self._last_time == 0.0: self._last_time = time.time() else: ds = time.time() - self._last_time self._last_time = time.time() self._stat_jitter.update(ds)
[docs]class TimeStrategies: (BestEffort, FixedSimulationStep) = range(2) internal_mapping = { BestEffort: { "impl": BestEffortStrategy, "python_repr": b"TimeStrategies.BestEffort", "human_repr" : "Best Effort" }, FixedSimulationStep: { "impl": FixedSimulationStepStrategy, "python_repr": b"TimeStrategies.FixedSimulationStep", "human_repr": "Fixed Simulation Step" } } @staticmethod
[docs] def make(strategy): try: return TimeStrategies.internal_mapping[strategy]["impl"]() except KeyError: return None
@staticmethod
[docs] def python_repr(strategy): try: return TimeStrategies.internal_mapping[strategy]["python_repr"] except KeyError: return None
@staticmethod
[docs] def human_repr(strategy): try: return TimeStrategies.internal_mapping[strategy]["human_repr"] except KeyError: return None
[docs]def time_isafter(t1, t2): """ Returns true if t1 > t2 in morse_time. Returns false otherwise """ return t2 - t1 < blenderapi.persistantstorage().time.mean / 2