From 26908040eb8e57a6177fb45b6e61888f08e8300a Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Fri, 10 Jun 2022 10:02:45 +0200 Subject: [PATCH] pybricks.common: Add CommonColorSensor class. Fixes https://github.com/pybricks/pybricks-api/issues/103 --- doc/main/nxtdevices.rst | 6 ++ src/pybricks/_common.py | 142 +++++++++++++++++++++++++++++ src/pybricks/nxtdevices.py | 46 +--------- src/pybricks/pupdevices.py | 177 ++---------------------------------- src/pybricks/pupdevices.pyi | 19 ---- 5 files changed, 161 insertions(+), 229 deletions(-) diff --git a/doc/main/nxtdevices.rst b/doc/main/nxtdevices.rst index 3285e76..c02bd0b 100644 --- a/doc/main/nxtdevices.rst +++ b/doc/main/nxtdevices.rst @@ -45,6 +45,12 @@ NXT Color Sensor .. automethod:: pybricks.nxtdevices.ColorSensor.rgb + .. rubric:: Advanced color sensing + + .. automethod:: pybricks.nxtdevices.ColorSensor.hsv + + .. automethod:: pybricks.nxtdevices.ColorSensor.detectable_colors + .. rubric:: Built-in light This sensor has a built-in light. You can make it red, green, blue, or turn diff --git a/src/pybricks/_common.py b/src/pybricks/_common.py index fed7687..343daf4 100644 --- a/src/pybricks/_common.py +++ b/src/pybricks/_common.py @@ -987,3 +987,145 @@ class IMU(Accelerometer): this returns a vector of accelerations along all axes. """ pass + + +class CommonColorSensor: + """Generic color sensor that supports Pybricks color calibration.""" + + def __init__(self, port: Port): + """__init__(port) + + Arguments: + port (Port): Port to which the sensor is connected. + """ + pass + + def color(self) -> Color: + """color() -> Color + + Scans the color of a surface. + + You choose which colors are detected using the + ``detectable_colors()`` method. By default, it detects + ``Color.RED``, ``Color.YELLOW``, ``Color.GREEN``, ``Color.BLUE``, + ``Color.WHITE``, or ``Color.NONE``. + + Returns: + Detected color. + """ + pass + + def hsv(self) -> Color: + """hsv() -> Color + + Scans the color of a surface. + + This method is similar to ``color()``, but it gives the full range + of hue, saturation and brightness values, instead of rounding it to the + nearest detectable color. + + Returns: + Measured color. The color is described by a hue (0--359), a + saturation (0--100), and a brightness value (0--100). + """ + pass + + def ambient(self) -> int: + """ambient() -> int: % + + Measures the ambient light intensity. + + Returns: + Ambient light intensity, ranging from 0% (dark) + to 100% (bright). + """ + pass + + def reflection(self) -> int: + """reflection() -> int: % + + Measures how much a surface reflects the light emitted by the + sensor. + + Returns: + Measured reflection, ranging from 0% (no reflection) to + 100% (high reflection). + """ + pass + + @overload + def detectable_colors(self, colors: Collection[Color]) -> None: + ... + + @overload + def detectable_colors(self) -> Tuple[Color]: + ... + + def detectable_colors(self, *args): + """ + detectable_colors(colors) + detectable_colors() -> Tuple[Color] + + Configures which colors the ``color()`` method should detect. + + Specify only colors that you wish to detect in your application. + This way, the full-color measurements are rounded to the nearest + desired color, and other colors are ignored. This improves reliability. + + If you give no arguments, the currently chosen colors will be returned + as a tuple. + + Arguments: + colors (tuple): Tuple of :class:`Color <.parameters.Color>` + objects: the colors that you want to detect. You can pick + standard colors such as ``Color.MAGENTA``, or provide your + own colors like ``Color(h=348, s=96, v=40)`` for even + better results. You measure your own colors with the + ``hsv()`` method. + """ + pass + + +class AmbientColorSensor(CommonColorSensor): + """Like CommonColorSensor, but also detects ambient colors when the sensor + light is turned off""" + + def color(self, surface: bool = True) -> Optional[Color]: + """color(surface=True) -> Color + + Scans the color of a surface or an external light source. + + You choose which colors are detected using the + ``detectable_colors()`` method. By default, it detects + ``Color.RED``, ``Color.YELLOW``, ``Color.GREEN``, ``Color.BLUE``, + ``Color.WHITE``, or ``Color.NONE``. + + Arguments: + surface (bool): Choose ``true`` to scan the color of objects + and surfaces. Choose ``false`` to scan the color of + screens and other external light sources. + + Returns: + Detected color.` + """ + pass + + def hsv(self, surface: bool = True) -> Color: + """hsv(surface=True) -> Color + + Scans the color of a surface or an external light source. + + This method is similar to ``color()``, but it gives the full range + of hue, saturation and brightness values, instead of rounding it to the + nearest detectable color. + + Arguments: + surface (bool): Choose ``true`` to scan the color of objects + and surfaces. Choose ``false`` to scan the color of + screens and other external light sources. + + Returns: + Measured color. The color is described by a hue (0--359), a + saturation (0--100), and a brightness value (0--100). + """ + pass diff --git a/src/pybricks/nxtdevices.py b/src/pybricks/nxtdevices.py index 832e05f..543f26c 100644 --- a/src/pybricks/nxtdevices.py +++ b/src/pybricks/nxtdevices.py @@ -4,10 +4,10 @@ """Use LEGO® MINDSTORMS® NXT motors and sensors with the EV3 brick.""" -from .parameters import Port, Color +from .parameters import Port from .iodevices import AnalogSensor -from ._common import ColorLight +from ._common import ColorLight, CommonColorSensor from typing import Callable, Optional, Tuple @@ -69,51 +69,11 @@ class LightSensor: pass -class ColorSensor(LightSensor): +class ColorSensor(CommonColorSensor): """LEGO® MINDSTORMS® NXT Color Sensor.""" light = ColorLight() - def __init__(self, port: Port): - """ColorSensor(port) - - Arguments: - port (Port): Port to which the sensor is connected. - """ - pass - - def color(self) -> Color: - """color() -> Color - - Measures the color of a surface. - - Returns: - ``Color.BLACK``, ``Color.BLUE``, ``Color.GREEN``, ``Color.YELLOW``, - ``Color.RED``, ``Color.WHITE`` or ``Color.NONE``. - """ - pass - - def ambient(self) -> int: - """ambient() -> int: % - - Measures the ambient light intensity. - - Returns: - Ambient light intensity, ranging from 0% (dark) to 100% (bright). - """ - pass - - def reflection(self) -> int: - """reflection() -> int: % - - Measures the reflection of a surface using a red light. - - Returns: - Reflection, ranging from 0% (no reflection) to 100% (high - reflection). - """ - pass - def rgb(self) -> Tuple[int, int, int]: """Measures the reflection of a surface using a red, green, and then a blue light. diff --git a/src/pybricks/pupdevices.py b/src/pybricks/pupdevices.py index b6b81fb..48dd734 100644 --- a/src/pybricks/pupdevices.py +++ b/src/pybricks/pupdevices.py @@ -11,9 +11,11 @@ from ._common import ( ColorLight as _ColorLight, Motor as _Motor, LightArray as _LightArray, + CommonColorSensor, + AmbientColorSensor, ) -from .parameters import Button as _Button, Color, Direction +from .parameters import Button as _Button, Color, Direction, Port class DCMotor(_DCMotor): @@ -112,93 +114,19 @@ class TiltSensor: pass -class ColorDistanceSensor: +class ColorDistanceSensor(CommonColorSensor): """LEGO® Powered Up Color and Distance Sensor.""" light = _ColorLight() - def __init__(self, port): - """ColorDistanceSensor(port) + def distance(self) -> int: + """distance() -> int: % - Arguments: - port (Port): Port to which the sensor is connected. - """ - pass - - def color(self): - """Scans the color of a surface. - - You choose which colors are detected using the - :meth:`.detectable_colors` method. By default, it detects - ``Color.RED``, ``Color.YELLOW``, ``Color.GREEN``, ``Color.BLUE``, - ``Color.WHITE``, or ``Color.NONE``. - - :returns: - Detected color. - :rtype: :class:`Color <.parameters.Color>` - """ - pass - - def ambient(self): - """Measures the ambient light intensity. - - Returns: - :ref:`percentage`: Ambient light intensity, ranging from 0 (dark) - to 100 (bright). - """ - pass - - def reflection(self): - """Measures the reflection of a surface. - - Returns: - :ref:`percentage`: Reflection, ranging from 0.0 (no reflection) to - 100.0 (high reflection). - """ - pass - - def detectable_colors(self, colors): - """Configures which colors the :meth:`.color` method should detect. - - Specify only colors that you wish to detect in your application. - This way, the full-color measurements are rounded to the nearest - desired color, and other colors are ignored. This improves reliability. - - If you give no arguments, the currently chosen colors will be returned - as a tuple. - - Arguments: - colors (list): Tuple of :class:`Color <.parameters.Color>` objects: - the colors that you want to detect. You can pick - standard colors such as ``Color.MAGENTA``, or provide your own - colors like ``Color(h=348, s=96, v=40)`` for even - better results. You measure your own colors with the - :meth:`.hsv` method. - """ - pass - - def hsv(self): - """Scans the color of a surface. - - This method is similar to :meth:`.color`, but it gives the full range - of hue, saturation and brightness values, instead of rounding it to the - nearest detectable color. - - :returns: - Measured color. The color is described by a hue (0--359), a - saturation (0--100), and a brightness value (0--100). - :rtype: :class:`Color <.parameters.Color>` - - """ - pass - - def distance(self): - """Measures the relative distance between the sensor and an object + Measures the relative distance between the sensor and an object using infrared light. Returns: - :ref:`relativedistance`: Relative distance ranging from 0 (closest) - to 100 (farthest). + Distance ranging from 0% (closest) to 100% (farthest). """ pass @@ -231,103 +159,18 @@ class PFMotor(DCMotor): pass -class ColorSensor: +class ColorSensor(AmbientColorSensor): """LEGO® SPIKE Color Sensor.""" lights = _LightArray(3) - def __init__(self, port): - """ColorSensor(port) - - Arguments: - port (Port): Port to which the sensor is connected. - - """ - pass - - def color(self, surface=True): - """Scans the color of a surface or an external light source. - - You choose which colors are detected using the - :meth:`.detectable_colors` method. By default, it detects - ``Color.RED``, ``Color.YELLOW``, ``Color.GREEN``, ``Color.BLUE``, - ``Color.WHITE``, or ``Color.NONE``. - - Arguments: - surface (bool): Choose ``true`` to scan the color of objects - and surfaces. Choose ``false`` to scan the color of - screens and other external light sources. - :returns: - Detected color. - :rtype: :class:`Color <.parameters.Color>` - """ - pass - - def detectable_colors(self, colors): - """Configures which colors the :meth:`.color` method should detect. - - Specify only colors that you wish to detect in your application. - This way, the full-color measurements are rounded to the nearest - desired color, and other colors are ignored. This improves reliability. - - If you give no arguments, the currently chosen colors will be returned - as a tuple. - - Arguments: - colors (list): Tuple of :class:`Color <.parameters.Color>` objects: - the colors that you want to detect. You can pick - standard colors such as ``Color.MAGENTA``, or provide your own - colors like ``Color(h=348, s=96, v=40)`` for even - better results. You measure your own colors with the - :meth:`.hsv` method. - """ - pass - - def hsv(self, surface=True): - """Scans the color of a surface or an external light source. - - This method is similar to :meth:`.color`, but it gives the full range - of hue, saturation and brightness values, instead of rounding it to the - nearest detectable color. - - Arguments: - surface (bool): Choose ``true`` to scan the color of objects - and surfaces. Choose ``false`` to scan the color of - screens and other external light sources. - - :returns: - Measured color. The color is described by a hue (0--359), a - saturation (0--100), and a brightness value (0--100). - :rtype: :class:`Color <.parameters.Color>` - - """ - pass - - def ambient(self): - """Measures the ambient light intensity. - - Returns: - :ref:`percentage`: Ambient light intensity, ranging from 0 (dark) - to 100 (bright). - """ - pass - - def reflection(self): - """Measures the reflection of a surface. - - Returns: - :ref:`percentage`: Reflection, ranging from 0.0 (no reflection) to - 100.0 (high reflection). - """ - pass - class UltrasonicSensor: """LEGO® SPIKE Color Sensor.""" lights = _LightArray(3) - def __init__(self, port): + def __init__(self, port: Port): """UltrasonicSensor(port) Arguments: diff --git a/src/pybricks/pupdevices.pyi b/src/pybricks/pupdevices.pyi index c43ff26..bcd3b29 100644 --- a/src/pybricks/pupdevices.pyi +++ b/src/pybricks/pupdevices.pyi @@ -14,25 +14,6 @@ from ._common import ( from .parameters import Color, Port -class ColorDistanceSensor: - light: ColorLight - def __init__(self, port: Port): ... - def color(self) -> Optional[Color]: ... - def ambient(self) -> int: ... - def reflection(self) -> int: ... - def detectable_colors(self, colors: Collection[Color]) -> None: ... - def hsv(self) -> Color: ... - def distance(self) -> int: ... - -class ColorSensor: - lights: LightArray - def __init__(self, port: Port): ... - def color(self, surface: bool = True) -> Optional[Color]: ... - def detectable_colors(self, colors: Collection[Color]) -> None: ... - def hsv(self, surface: bool = True) -> Color: ... - def ambient(self) -> int: ... - def reflection(self) -> int: ... - class UltrasonicSensor: lights: LightArray def __init__(self, port: Port): ...