api/_common/Light: introduce pattern

Currently, Pybricks has system patterns for builtin lights.
This adds a user method to set such a pattern.

For example, an indefinite sine pattern could be specified by

def fade(time):
    return sin(time/2000/pi)*50+50

hub.light.pattern(fade, 1000)

or a blinking pattern using

def blink(time):
    if time >= 1000:
        return 100
    else:
        return 0

hub.light.pattern(blink, 2000)

or briefly:

hub.light.pattern(lambda t: 100 if t >= 1000 else 0, 2000)

This combines the best of simplicity and efficiency: The user doesn't
have to calculate and provide an expensive list of floating points, but
provide a clean and adaptable method instead.
By sampling, we maintain a fixed length pattern which we can preallocate
for the hub lights, and the samples are calculated only once and the
callable may be garbage collected if given as lambda. Also, any
exceptions will be caught immediately during the one-off evaluation.
This commit is contained in:
Laurens Valk
2020-07-07 09:44:16 +02:00
committed by laurensvalk
parent 20fec6461a
commit b8505ff218
+19
View File
@@ -404,6 +404,25 @@ class Light:
"""Turns off the light."""
pass
def pattern(self, pattern, duration, repeat=True):
"""Make the light brightness follow a pattern as a function of time.
The specified pattern function will be sampled at 64 points between 0
and the specified duration. The light will be held at a constant
brightness between samples.
This function is not blocking. The pattern will be shown as the
user program continues.
Arguments:
pattern (callable): Function of the
form ``b = func(t)``` that returns the brightness ``b``
of the (0--100.0) as a function of time ``t`` in milliseconds.
time (:ref:`time`): Duration of the pattern.
repeat (bool): Whether to keep repeating the pattern after it
completes.
"""
class ColorLight:
"""Control a multi-color light."""