Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python3 support #11

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
*.pyc
*.so
imusim/maths/*.c
imusim/maths/*.html
build
docs/build
.idea
dist/
imusim.egg-info/
.DS_Store
tests*.txt

15 changes: 8 additions & 7 deletions docs/imusim_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import inspect
import imusim
import imusim.all
import functools


def imusim_api_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
"""
Expand All @@ -12,7 +14,7 @@ def imusim_api_role(role, rawtext, text, lineno, inliner, options={}, content=[]

try:
# Look for object in imusim.all.
obj = reduce(lambda x,y: getattr(x,y), [imusim.all] + text.split('.'))
obj = functools.reduce(lambda x,y: getattr(x,y), [imusim.all] + text.split('.'))

if inspect.ismodule(obj):
file = '%s-module.html' % obj.__name__
Expand All @@ -34,18 +36,16 @@ def imusim_api_role(role, rawtext, text, lineno, inliner, options={}, content=[]
file = '%s.%s-class.html#%s' \
% (cls.__module__, cls.__name__, obj.__name__)
else:
raise TypeError, \
"Don't know how to document native object " + repr(obj)
raise TypeError("Don't know how to document native object " + repr(obj))
else:
raise TypeError, \
"Don't know how to document Python object " + repr(obj)
raise TypeError("Don't know how to document Python object " + repr(obj))
except AttributeError:
# Look for object as an imusim submodule.
__import__("imusim.%s" % text)
obj = reduce(lambda x,y: getattr(x,y), [imusim] + text.split('.'))
obj = functools.reduce(lambda x,y: getattr(x,y), [imusim] + text.split('.'))
file = 'imusim.%s-module.html' % text
except ImportError:
raise KeyError, "Could not find an IMUSim object called '%s'" % text
raise KeyError("Could not find an IMUSim object called '%s'" % text)

if inspect.ismethod(obj) \
or (inspect.isbuiltin(obj) and hasattr(obj, '__objclass__')):
Expand All @@ -59,5 +59,6 @@ def imusim_api_role(role, rawtext, text, lineno, inliner, options={}, content=[]

return [node], []


def setup(app):
app.add_role('api', imusim_api_role)
12 changes: 5 additions & 7 deletions imusim/algorithms/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,16 @@
#
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from __future__ import division
from scipy.optimize import leastsq
from abc import abstractmethod, ABCMeta
from abc import abstractmethod, ABC
import imusim.maths.vectors as vectors
import numpy as np

class SensorCalibration(object):

class SensorCalibration(ABC):
"""
Calibration data for a triaxial sensor.
"""
__metaclass__ = ABCMeta

@abstractmethod
def apply(measurement):
"""
Expand All @@ -40,6 +37,7 @@ def apply(measurement):
"""
pass


class ScaleAndOffsetCalibration(SensorCalibration):
"""
Calibration that corrects constant scale and offset errors.
Expand Down Expand Up @@ -83,7 +81,7 @@ def error(p):
p0 = np.array([1,1,1,0,0,0])
p, ier = leastsq(error, p0, ftol=1e-3, maxfev=10000)
if ier not in [1,2,3,4]:
raise ValueError, "Scale and offset fitting failed."
raise ValueError("Scale and offset fitting failed.")
return ScaleAndOffsetCalibration(*params(p))

def apply(self, measurement):
Expand Down
8 changes: 3 additions & 5 deletions imusim/algorithms/orientation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from __future__ import division
from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
from imusim.maths.quaternions import Quaternion
from imusim.maths import vectors
from imusim.maths.kalman import KalmanFilter
Expand All @@ -32,7 +31,8 @@
import numpy as np
import math

class OrientationFilter(object):

class OrientationFilter(ABC):
"""
Base class for orientation estimation filters.

Expand All @@ -43,8 +43,6 @@ class OrientationFilter(object):
@ivar rotation: L{TimeSeries} of quaternion orientation estimates.
"""

__metaclass__ = ABCMeta

def __init__(self, initialTime, initialRotation):
"""
Initialise orientation filter.
Expand Down
10 changes: 5 additions & 5 deletions imusim/algorithms/position.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
import numpy as np
import scipy.stats
import math
Expand All @@ -27,15 +27,14 @@
from imusim.utilities.time_series import TimeSeries
from imusim.utilities.documentation import prepend_method_doc

class PositionEstimator(object):

class PositionEstimator(ABC):
"""
Base class for position estimation algorithms.

A position estimator takes data from IMUs on a jointed rigid body and
updates the root position of a L{SampledBodyModel}.
"""
__metaclass__ = ABCMeta

def __init__(self, model, initialTime=0, initialPosition=np.zeros((3,1))):
"""
Initialise position estimator.
Expand Down Expand Up @@ -92,9 +91,10 @@ def getParameter(self, data, jointName, parameter, default=None):
parameter is not found in the passed data.
"""
for item in data:
if item.has_key('jointName') and item['jointName'] == jointName:
if item.get('jointName') == jointName:
return item.get(parameter, default)


class ConstantPosition(PositionEstimator):
"""
Trivial position estimator that gives a constant position.
Expand Down
14 changes: 7 additions & 7 deletions imusim/algorithms/posture_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
from imusim.trajectories.rigid_body import SampledBodyModel
from imusim.maths.quaternions import Quaternion
from imusim.platforms.radios import RadioPacket

class PostureReconstructor(object):

class PostureReconstructor(ABC):
"""
Base class for posture reconstruction algorithms.

A posture estimator takes data from IMUs on a jointed rigid body and
updates the joint rotations of a L{SampledBodyModel}.
"""
__metaclass__ = ABCMeta

def __init__(self, bodyModel, initialJointRotations=[]):
def __init__(self, bodyModel, initialJointRotations=()):
"""
Initialise posture reconstructor.

Expand Down Expand Up @@ -78,6 +77,7 @@ def _update(self, joint, data, dt, t):
"""
pass


class SimpleForwardKinematics(PostureReconstructor):
"""
Posture reconstructor using joint orientations directly.
Expand All @@ -87,7 +87,7 @@ def __init__(self, bodyModel):
PostureReconstructor.__init__(self, bodyModel)

def _update(self, joint, data, dt, t):
if data is not None and data.has_key('rotation'):
if data is not None and 'rotation' in data:
joint.rotationKeyFrames.add(t, data['rotation'])


Expand All @@ -104,7 +104,7 @@ def __init__(self, bodyModel):
PostureReconstructor.__init__(self, bodyModel)

def _update(self, joint, data, dt, t):
if data is not None and data.has_key('rotation'):
if data is not None and 'rotation' in data:
joint.rotationKeyFrames.add(t, data['rotation'])
elif joint.hasParent:
joint.rotationKeyFrames.add(t, joint.parent.rotation(t))
Expand Down
14 changes: 9 additions & 5 deletions imusim/algorithms/vector_observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from __future__ import division
from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
from imusim.maths.quaternions import Quaternion
from scipy.optimize import newton
import imusim.maths.vectors as vectors
from imusim.utilities.documentation import prepend_method_doc
import numpy as np
import math

class VectorObservation(object):

class VectorObservation(ABC):
"""
Base class for all vector observation methods.

Vector observation methods calculate the L{Quaternion} that rotates a
set of reference vectors to match the set of observed vectors.
Vectors are assumed to be 3x1 L{np.ndarray}s
"""

__metaclass__ = ABCMeta

def __call__(self, *measurements):
"""
Estimate the orientation Quaternion from the observed vectors.
Expand All @@ -63,6 +61,7 @@ def _process(self, *measurements):
"""
pass


class TRIAD(VectorObservation):
"""
Implementation of the TRIAD vector observation algorithm.
Expand Down Expand Up @@ -91,6 +90,7 @@ def _process(self, g, m):

return Quaternion.fromVectors(x, y, z)


class GramSchmidt(VectorObservation):
"""
Vector observation based on Gram-Schmidt Ortho-Normalisation.
Expand All @@ -109,6 +109,7 @@ def _process(self, g, m):

return Quaternion.fromVectors(x, y, z)


class FQA(VectorObservation):
"""
Implementation of the Factored Quaternion Algorithm by Yun et al.
Expand Down Expand Up @@ -208,6 +209,7 @@ def _process(self, g, m):
else:
return combined


class LeastSquaresOptimalVectorObservation(VectorObservation):
"""
Base class of least squares optimal vector observation algorithms
Expand Down Expand Up @@ -249,6 +251,7 @@ def __init__(self, refs=None, weights=None, inclinationAngle=None):
self.refs = np.asarray(refs)
self.weights = np.asarray(weights) / sum(weights)


class DavenportQ(LeastSquaresOptimalVectorObservation):
"""
Implementation of the Davenport-q algorithm.
Expand Down Expand Up @@ -282,6 +285,7 @@ def _process(self, *meas):

return Quaternion(q[3],q[0],q[1],q[2]).normalise()


class QUEST(LeastSquaresOptimalVectorObservation):
"""
Implementation of the QUEST algorithm.
Expand Down
4 changes: 3 additions & 1 deletion imusim/all/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import inspect

__all__ = []
path = os.path.split(pkgutil.get_loader('imusim').filename)[0]
path = os.path.split(os.path.dirname(pkgutil.get_loader('imusim').path))[0]
for loader, modname, ispkg in pkgutil.walk_packages([path]):
if modname in ['imusim.visualisation.rendering', 'imusim.visualisation.video']:
continue
if modname.startswith('imusim') \
and not modname.startswith('imusim.tests') \
and not modname.startswith('imusim.all'):
Expand Down
8 changes: 3 additions & 5 deletions imusim/behaviours/imu.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.
from abc import ABCMeta
from abc import ABC
from imusim.utilities.time_series import TimeSeries
from imusim.behaviours.timing import TimerMultiplexer, VirtualTimer
from imusim.behaviours.sampling import PeriodicSampler
Expand All @@ -26,7 +26,8 @@
from imusim.algorithms.orientation import OrientationFilter
from imusim.platforms.imus import IMU

class BasicIMUBehaviour(object):

class BasicIMUBehaviour(ABC):
"""
Basic behaviour for an IMU that performs periodic sampling.

Expand All @@ -39,9 +40,6 @@ class BasicIMUBehaviour(object):
object will be passed as a single argument.
@ivar timerMux: L{TimerMultiplexer} for IMU timer.
"""

__metaclass__ = ABCMeta

def __init__(self, imu, samplingPeriod, calibration=None, filter=None,
sampleCallback=None, initialTime=0):
"""
Expand Down
10 changes: 3 additions & 7 deletions imusim/behaviours/mac.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,22 @@
#
# You should have received a copy of the GNU General Public License
# along with IMUSim. If not, see <http://www.gnu.org/licenses/>.

from __future__ import division
from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
from imusim.platforms.base import Platform
from imusim.platforms.radios import Radio, RadioPacket
from imusim.behaviours.timing import TimerMultiplexer
from imusim.maths.quaternions import Quaternion
from imusim.utilities.documentation import prepend_method_doc
import numpy as np

class MAC(object):

class MAC(ABC):
"""
Base class for MAC implementations.

@ivar radio: The L{Radio} used by the MAC.
@ivar timerMux: L{TimerMultiplexer} used by the MAC.
"""

__metaclass__ = ABCMeta

def __init__(self, radio, timerMux):
"""
Initialise MAC.
Expand Down
4 changes: 2 additions & 2 deletions imusim/behaviours/orient_tdma.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from imusim.utilities.documentation import prepend_method_doc
import numpy as np

class Schedule(object):
class Schedule:
"""
Transmission schedule.
"""
Expand Down Expand Up @@ -243,7 +243,7 @@ def _slotTimerHandler(self):
self.auxSlot = 0
else:
self.auxSlot += 1
if self.slot < self.schedule.dataSlots:
if self.slot in self.schedule.dataSlots:
self.auxSlotTimer.start(self.schedule.dataSlotTime/2)
if self.auxSlot in self.auxTxSlots + self.auxRxSlots:
self.radio.channel = self.schedule.auxChannel
Expand Down
Loading