sensors.InertialSensor

class sensors.InertialSensor(port: Optional[int] = None)

Sensor for measuring relative acceleration, rotation, and angular velocity. Also referred to as the “Inertial Measurement Unit” or IMU for short.

acceleration() Vector3

Instantaneous acceleration in meters per second per second relative to the sensors current orientation. A slight filter is applied. For an unfiltered version, see acceleration_stream().

The following code block assumes an interial sensor is assigned to port 0 and a TextScreen is attatched to port 1.

from sensors import InertialSensor
from controllables import TextScreen
from color import Color

imu = InertialSensor(0)
screen = TextScreen(1)

while True:
    screen.text = f"{imu.acceleration(): 4.0f}"
    redness = min(1,max(0,imu.acceleration().magnitude() / 10))
    screen.color = Color(redness,1 - redness,0)
acceleration_stream() Stream[Vector3]

Creates an unfiltered stream of acceleration values in meters per second per second relative to the sensors current orientation.

from sensors import InertialSensor
from controllables import TextScreen
from time import time
from vector import Vector3

stream = InertialSensor().acceleration_stream()

acceleration_threshold = 5


screen = TextScreen()

screen.text = ''
time_of_last_color_hit = time()

while True:
        for acceleration in stream:
                flattened = Vector3.project_onto_plane(acceleration,[0,1,0])
                if flattened.magnitude() > acceleration_threshold:
                        time_of_last_color_hit = time()
                        screen.text = "We've changed velocity!"
        if time() - time_of_last_color_hit > 1:
                screen.text = ''
                pass
rotation_axis() Vector3

Axis of rotation whose magnitude is the magnitude of the rotation in radians.

A value of <x = tau/2.,y = 0,z = 0> means a half rotation about the x axis. A rotation of <x = 1/sqrt(2),y = 1/sqrt(2),z = 0> * tau/4.0 does not have anything to do with rotations about either the x or y axis, but is instead a quarter rotation around the diagonal vector pointing up and to the right.

The returned axis is the rotation required to rotate from the sensor’s initial orientation to its current one. The axis is given in the space of the sensors current axes.

The following example assumes that an inertial sensor is assigned to port 0 and a ServoMotor is assigned to port 1. It assumes that the motor and sensor are sitting on the base of a moving robot and that the motor is placed facing up. The script will try keep the motor’s arm pointed in the direction in which it was initially facing.

from sensors import InertialSensor
from controllables import ServoMotor
from vector import Vector3

imu = InertialSensor(0)
servo = ServoMotor(1)

while True:
    servo.spin_to(-imu.rotation_axis().y)
rotation_stream() Stream[Vector3]

Creates an unfiltered stream of rotation axis values in radians.

from sensors import InertialSensor
from scriptruntime import Runtime
from controllables import TextScreen
from math import tau

stream = InertialSensor().rotation_stream()
screen = TextScreen()

integrated_rotation = 0


while True:
        for rot in stream:
                rot_y = rot.y % tau
                if rot_y > tau / 2:
                        rot_y -= tau
                integrated_rotation += rot.y * Runtime.sample_duration()
        screen.text = f'integral of rotation: {integrated_rotation: 0.2f}'
euler_angles() Vector3

Returns the pitch, yaw and roll of the sensor in the form of a vector3 where x, y, and z components are respectively pitch, yaw and roll in radians.

from sensors import InertialSensor
from controllables import TextScreen


sensor = InertialSensor()
screen = TextScreen()


while True:
        [pitch,yaw,roll] = sensor.euler_angles()
        screen.text = f'pitch: {pitch: 5.2f}\n' + \
                    f'yaw:   {yaw: 5.2f}\n' + \
                    f'roll:  {roll: 5.2f}\n'
x_unit() Vector3

The vector, with length 1, pointed in the part’s x axis relative to the part’s original orientation.

from sensors import InertialSensor
from controllables import TextScreen


sensor = InertialSensor()
screen = TextScreen()


while True:
        right = sensor.x_unit()
        screen.text = f'right: {right: 5.1f}'
y_unit() Vector3

The vector, with length 1, pointed in the part’s y axis relative to the part’s original orientation.

from sensors import InertialSensor
from controllables import TextScreen


sensor = InertialSensor()
screen = TextScreen()


while True:
        flipped = sensor.y_unit().y < 0
        screen.text = f'flipped? {flipped}'
z_unit() Vector3

The vector, with length 1, pointed in the part’s z axis relative to the part’s original orientation.

from sensors import InertialSensor
from controllables import TextScreen


sensor = InertialSensor()
screen = TextScreen()


while True:
        forward = sensor.z_unit()
        screen.text = f'forward: {forward: 5.1f}'
angular_velocity() Vector3

Angular velocity relative to the sensors current orientation in radians per second. A velocity of <2 * tau,0,0> means the sensor is rotating around it’s own x axis twice per second. A slight filter is applied, see angular_velocity_stream() for an unfiltered version.

from sensors import InertialSensor
from controllables import TextScreen

sensor = InertialSensor()
screen = TextScreen()

while True:
    screen.text = f'angular velocity: {sensor.angular_velocity(): 5.1f}'
angular_velocity_stream() Stream[Vector3]

Creates an stream of angular velocity values in radians per second.

from sensors import InertialSensor
from controllables import TextScreen
from time import time

stream = InertialSensor().angular_velocity_stream()

vel_threshold = 5


screen = TextScreen()

screen.text = ''
time_of_last_turn = time()

while True:
        for vel in stream:
                if vel.magnitude() > vel_threshold:
                        time_of_last_turn = time()
                        screen.text = "We've been turned too fast!"
        if time() - time_of_last_turn > 1:
                screen.text = ''
class MotionData(rotation_axis: Vector3, angular_velocity: Vector3, acceleration: Vector3)

Holds rotation, angular velocity, and acceleration data from the same sample.

See motion_data_stream() for example usage.

motion_data_stream() Stream[MotionData]

Creates a stream which contains samples from each data stream together such that in a given data object all samples were recorded simultaneously. The values all correspond directly to the other streams avaliable in this class.

The following example gets the motion data from an InertialSensor on port 0 and outputs the velocity to a TextScreen on port 1.

from sensors import InertialSensor
from matrix import Matrix4x4
from scriptruntime import Runtime
from vector import Vector3
from controllables import TextScreen

imu = InertialSensor(0)
output = TextScreen(1)

stream = imu.motion_data_stream()
dt = Runtime.sample_duration()
velocity = Vector3(0,0,0)

while True:
    for sample in stream:
        acc          = sample.acceleration
        rot          = sample.rotation_axis
        rot_matrix   = Matrix4x4.from_rotation(rot)
        # rotate the acceleration to get a vector relative to a fixed frame
        dv           = rot_matrix * acc

        # use the sample duration here to do the integration
        velocity += dv * dt

    output.text = f"{velocity:+4.1f}"
name() str

Returns the user editable name of the controllable as found in the properties tab of the game.

The following example assumes that any controllable or sensor is assigned to port 0 and prints out its name.

from ports import PortReference

print(PortReference(0).name())