Laboratory

So here we go with the lab. This is a very rough implementation of what I had in mind, so @matze can feel free to chip in. I tried to keep it simple and also extensible, that's why there are the position default arguments. Usage example:

import numpy as np
from concert.quantities import q
from concert.devices.motors.dummy import LinearMotor, RotationMotor
from concert.devices.positioners.base import Axis, Positioner
from concert.devices.cameras.dummy import Camera
from concert.devices.detectors.dummy import Detector # Not yet existing

x_axis = Axis('x', LinearMotor())
y_axis = Axis('y', LinearMotor())
z_axis = Axis('z', LinearMotor())
y_rot_axis = Axis('y', RotationMotor())
positioner = Positioner([x_axis, y_axis, z_axis, y_rot_axis])

# Move to the center of origin
positioner.position = (0, 0, 0) * q.mm
# Move to the right
positioner.position = (10, 0, 0) * q.mm
# Rotate 90 degrees counter clockwise
positioner.orientation = (0, - 90, 0) * q.deg

camera = Camera()
detector = Detector(camera, 3)

# Move to the right 10 pixels (that will need to get simpler and nicer)
pixel_vector = (10, 0, 0) * q.dimensionless
positioner.move(pixel_vector * detector.pixel_width)

As usual:
* [ ] fix tests
* [ ] add more tests (both detector and positioner)
* [ ] update the docs