7. Colorsensor


Der EV3 ColorSensor kann wie ein LichtSensor die Lichtintensität messen (siehe Lichtsensor) und darüber hinaus Farben erkennen. Der Sensor ist mit Leuchtdioden (LEDs) zur Beleuchtung einer Fläche und Fotodioden ausgestattet, welche die rote, grüne und blaue Komponente des reflektierenden Lichts misst.
 

Die RGB-Werte, die der Sensor zurückmeldet, sind abhängig von der Umgebungsbeleuchtung und von der Entfernung zum Objekt. Die besten Ergebnisse erreicht man in einer Entfernung von 0.5 - 1 cm.

Die Bibliotheken ev3robot und simrobot stellen für die Erfassung der Farben mehrere Methoden zur Verfügung:

  • Erkennung der 6 Standardfarben mit den Methoden getColorID() und getColorStr()
  • Anpassung des vordefinierten Farbraums mit den Methoden getColor() und inColorCube()

Standardfarben:

1
2
3
4
5
6
 

Die Methode getColorID() gibt eine Farbnummer 1 - 6 zurück. Die Methode getColorStr() liefert einen Farbnamen (BLACK, BLUE, GREEN, YELLOW, RED, WHITE)


Beispiel 1: 6 Farben erkennen

Der Roboter mit einem Farbsensor wird auf einen Farbstreifen gestellt. Der Farbsensor registriert die darunterliegende Farbe und zeigt den Farbnamen auf dem LCD-Display an Wenn er eine Farbe nicht erkennt, wird UNDEFINED ausgeschrieben.
(Farbstreifen zum Drucken: colorstrip.pdf)

Anstelle von Farbstreifen können die roten, blauen, gelben und grünen Bausteine aus dem Lego-Bausatz benutzt werden.

 
Realmodus   Simulationsmodus
# Ro7a.py

from ev3robot import *
#from nxtrobot import *
                                 
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear.setSpeed(10)
gear.forward()

while not robot.isEscapeHit():
   c = cs.getColorStr()
   print(c)
   robot.drawString(c, 0, 1)
   Tools.delay(300)
robot.exit()
 
# Sim7a.py

from simrobot import *

RobotContext.useBackground("sprites/colors.png") 
RobotContext.setStartPosition(250, 480)
RobotContext.showStatusBar(30)                                 
                                 
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear.setSpeed(20)
gear.forward()

while not robot.isEscapeHit():
   c = cs.getColorStr()
   print(c)
   Tools.delay(300)
robot.exit()
Programmcode markieren (Ctrl+C kopieren)
 
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

cs = ColorSensor(SensorPort.S3): erzeugt ein Colorsensorobjekt
get.ColorStr(): liefert den Farbwert der Standardfarben als Enum mit den Werten BLACK, BLUE, GREEN, YELLOW, RED und WHITE
print(c): zeigt der Farbwert im Ausgabefenster des TigerJython-Editors an (nur im direkten und Simulationsmodus)
robot.drawString(c, 0, 1) zeigt den Farbwert als String auf dem LCD-Display der Roboters an (in der Zeile 0 und Spalte 1). Im Simulationsmodus erschent diese Anzeige in der Staturbar
RobotContext.useBackground("sprites/colors.png"): das Hintergrundbild colors.png wird im Simulationsmodus benutzt
RobotContext.showStatusBar(30) : für zum Simulationsfenster eine Statusbar hinzu, in der mit robot.drawString() Werte ausgeschriben werden können (ersetzt die Anzeige auf dem LCD-Display).

Beispiel 2: Den Farbraum anpassen
Die Methode getColor() liefert die Farbwerte als Typ java.awt.Color, aus welchen im Realmodus die rote, grüne und blaue Komponente mit getRed(), gerGreen() und getBlue() als eine ganze Zahl zwischen 0 und 255 bestimmen werden können. Man muss damit rechnen, dass diese Sensorwerte Messfehler auweisen und daher nicht eindeutig sind. Um diese Abweichungen zu erfassen, legen wir im Farbraum mehrere Quader fest, in denen die Messwerte liegen müssen. Die Quader sind durch einer Liste mit den roten, grünen und blauen Bereichen [red_min, red_max, green_min, green_max, blue_min, blue_max] definiert. Die 6 Standard-Farben im Beispiel 1 sind wie folgt festgelegt:

blackCube = [0, 10, 0, 10, 0, 10]
blueCube = [5, 15, 10, 25, 15, 45]
greenCube = [8, 24, 25, 65, 3, 15]
yellowCube = [50, 90, 35, 90, 3, 20]
redCube = [40, 90, 5, 15, 3, 12]
whiteCube = [40, 120, 40, 120, 40, 120]

 

 

Falls die Farberkennung zum Beispiel für die blaue Farbe nicht korrekt ist, können die Werte für blueCube angepasst werden. Zuerst lässt man die drei Farbkomponenten anzeigen (für die blaue Farbe beispielweise r = 10, g = 12, b = 52). Liegen diese Werte nicht in den vordefinierten Bereichen, müssen die blueCube-Werte angepasst werden: cs.colorCubes[1] = [5, 15, 10, 25, 15, 60]
Danach können wieder die Methoden getColorStr() und getColorId() wie im Beispiel 1 verwendet werden.
Im Simulationsmodus entsprechen die Sensorfarben den Farben der Backgroundbilder. Die ColorCubes können ebenfalls angepasst werden, falls bei selbsterstellten Bildern die Farbwerte nicht den Standardfarben entsprechen..


Realmodus   Simulationsmodus
# Ro7b.py

from ev3robot import *
  
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
# Redefine blue color cube
cs.colorCubes[1] = [5,15, 10,25, 15,60]
# Redefine green color cube
cs.colorCubes[2] = [5,25, 30,85, 5,25]
gear.setSpeed(10)
gear.forward()

while not robot.isEscapeHit():
   c = cs.getColor()
   s = cs.getColorStr()
   print (c.getRed(),c.getGreen(),c.getBlue(), s)
   robot.drawString(s, 0, 1)
   Tools.delay(300)
robot.exit()

 
# Sim7b.py

from simrobot import *

RobotContext.useBackground("sprites/colors.png") 
RobotContext.setStartPosition(250, 480)
RobotContext.showStatusBar(30)                           
                                 
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
cs.colorCubes[1] = [0, 10, 0, 10, 200, 255]
cs.colorCubes[2] = [0, 10, 200, 255, 0, 10]
gear.forward();

while not robot.isEscapeHit():
   c = cs.getColor()
   color = cs.getColorStr()
   print(color)
   robot.drawString(color, 0, 1)
   Tools.delay(300)
robot.exit()
Programmcode markieren (Ctrl+C kopieren)
 
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

cs.colorCube[1] = [5, 15, 10, 25, 15, 60]: modifiziert die blueCube
cs.getColor(): liefer den Farbwert
c. getColorStr(): liefert die Farbe als String (BLACK, BLUE, GREEN, YELLOW, RED und WHITE
c. getRed(): liefert die rote Komponente der Farbe c (nur Realmodus)

 

Beispiel 3: Eigenen Farbraum definieren
Im Realmodus ist es einfach mit den Methoden getColor() und inColorCube() einen eigenen Farbraum für beliebige Farben zu definieren. Dabei geht man wie folgt vor:

- Zuerst lässt man mit der Methode getColor() die drei Farbkomponenten der neuen Farbe auf dem LCD anzeigen:
(für cyan Farbe beispielweise r = 10, g = 37, b = 36).
- dann definiert man cyanCube so dass diese Werte in den Bereichen liegen, z.B.
cyanCube = [0, 15, 30, 60, 30, 60]

Die Zahlen in der Klammer bedeuten:
[red_min, red_max, green_min, green_max, blue_min, blue_max].

 

Realmodus   Simulationsmodus
# Ro7c.py

from ev3robot import *
                                 
cyanCube = [0,20, 30,60, 30,60]
yellowCube = [50,90, 35,70, 3,20]
magentaCube = [40,60, 5,20, 10,60]
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear.setSpeed(10)
gear.forward()
color = "Undefined"

while not robot.isEscapeHit():
   c = cs.getColor()    
   if cs.inColorCube(c, cyanCube):
      color = "Cyan"
   elif cs.inColorCube(c, yellowCube):
      color = "Yellow"
   elif cs.inColorCube(c, magentaCube):
      color = "Magenta"
   else:
      color = "Undefined"
   print(c.getRed(), c.getGreen(), c.getBlue(), color)
   robot.drawString(color, 0, 1)  
   Tools.delay(300)
robot.exit()
 
# Sim7c.py

from simrobot import *

RobotContext.useBackground("sprites/colors2.png") 
RobotContext.setStartPosition(250, 480)
RobotContext.showStatusBar(30)                                 
cyanCube = [0, 10, 220, 255, 220, 255]
yellowCube = [220, 255, 220, 255, 0, 10]
magentaCube = [220, 255, 0, 10, 220, 255]
robot = LegoRobot()
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear = Gear()
robot.addPart(gear)
gear.setSpeed(20)
gear.forward()
color = "Undefined"

while not robot.isEscapeHit():
   c = cs.getColor()  
   if cs.inColorCube(c, cyanCube):
      color = "Cyan"
   elif cs.inColorCube(c, yellowCube):
      color = "Yellow"
   elif cs.inColorCube(c, magentaCube):
      color = "Magenta"
   else:
      color = "Undefined"
   print(color)
   Tools.delay(300)
robot.exit()
  
Programmcode markieren (Ctrl+C kopieren)
 
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

cyanCube = [0,10, 30,60, 30,60]: definiert cyanCube
if (cs.inColorCube(c, cyanCube)): Gibt true zurück, wenn sich die Farbe c in der cyanCube befindet

 

Beispiel 4: Farben und Sound
Der Roboter mit einem Farbsensor bewegt sich auf einem Farbstreifen mit den Farben Black, Blue, Yellow, Green, Red und White. Der Roboter spielt für jede Farbe einen anderen Ton ab. Der Ton wird nur abgespielt, wenn er eine neue Farbe sieht.

Mehr zum Befehl playTone() findet man unter Menüpunkt Sound abspielen oder unter Turtlegrafik/Sound.

 

Realmodus   Simulationsmodus
# Ro7d.py

from ev3robot import *
                                 
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear.setSpeed(10)
oldColor = "UNDEFINED"

while not robot.isEscapeHit():
    color = cs.getColorStr()
    if (color != oldColor):
        oldColor = color
        if color == "BLACK":
            robot.playTone(264, 300)
            gear.forward()
        elif color == "BLUE":
            robot.playTone(297, 300)
        elif color == "GREEN":
            robot.playTone(330, 300) 
        elif color == "YELLOW":
            robot.playTone(352, 300) 
        elif color == "RED":
            robot.playTone(396, 300)
            gear.backward() 
    print(color)
    robot.drawString(color, 0, 1)                        
robot.exit()
 
# Sim7d.py

from simrobot import *

RobotContext.useBackground("sprites/colors.png")
RobotContext.setStartPosition(250, 480)
RobotContext.showStatusBar(30)
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear.setSpeed(50)
gear.forward()
oldColor = "UNDEFINED"

while not robot.isEscapeHit():
    color = cs.getColorStr()
    if (color != oldColor):
        oldColor = color
        if color == "BLACK":
            robot.playTone(264, 500)
            gear.forward()
        elif color == "BLUE":
            robot.playTone(297, 500)
        elif color == "GREEN":
            robot.playTone(330, 500)
        elif color == "YELLOW":
            robot.playTone(352, 500)
        elif color == "RED":
            robot.playTone(396, 500)            
        elif color == "WHITE":       
            gear.backward() 
    print(color)                                   
robot.exit()
Programmcode markieren (Ctrl+C kopieren)
 
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

oldColor  = "Undefined": oldColor wird zu Beginn auf Udefined gesetzt
if (color != oldColor): Die Farbe wird kontinuierlich ermittelt, der Ton wird aber nur gespielt, wenn die Farbe ändert
robot.playTone(264, 300): Spielt einen Ton mit der Frequenz 264 Hz, während 300 Millisekunden

 

Beispiel 5: Speed Control
Der Roboter mit einem Colorsensor kann aufgrund der Farbe, die er "sieht" seine Geschwindigkeit anpassen. Auf einem grünen Streifen muss er schnell, auf dem gelben Streifen langsam fahren und bei rot muss er 2 Sekunden anhalten, bevor er wieder losfahren darf.

 

Realmodus   Simulationsmodus
# Ro7e.py

from ev3robot import *
                               
robot = LegoRobot()
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear = Gear()
robot.addPart(gear);
gear.setSpeed(20)
isRed = False

while not robot.isEscapeHit():   
   color = cs.getColorStr()
   print(color)
   robot.drawString(color, 0, 1)      
   if color == "BLACK":
      gear.setSpeed(50)
      gear.leftArc(0.1)
   elif color == "BLUE":
      gear.setSpeed(50)
      gear.rightArc(0.1)
   else:
      if color == "GREEN":
         gear.setSpeed(40);
         isRed = False
      elif color == "YELLOW":
         gear.setSpeed(10)
         isRed = False
      elif (color == "RED" and not isRed):
         gear.stop()
         isRed = True
         Tools.delay(1000)
         gear.setSpeed(20)
      gear.forward()
robot.exit()
 
# Sim7e.py

from simrobot import *

RobotContext.useBackground("sprites/colortrack.png") 
RobotContext.setStartPosition(430, 410)
RobotContext.showStatusBar(30)
robot = LegoRobot()
cs = ColorSensor(SensorPort.S3)
robot.addPart(cs)
gear = Gear()
robot.addPart(gear);
gear.setSpeed(20)
isRed = False

while not robot.isEscapeHit():   
   color = cs.getColorStr()
   print(color) 
   robot.drawString(color, 0, 1)     
   if color == "BLACK":
      gear.setSpeed(50)
      gear.leftArc(0.1)
   elif color == "BLUE":
      gear.setSpeed(50)
      gear.rightArc(0.1)
   else:
      if color == "GREEN":
         gear.setSpeed(40);
         isRed = False
      elif color == "YELLOW":
         gear.setSpeed(10)
         isRed = False
      elif (color == "RED" and not isRed):
         gear.stop()
         isRed = True
         Tools.delay(1000)
         gear.setSpeed(20)
      gear.forward()
robot.exit()
Programmcode markieren (Ctrl+C kopieren)
 
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

isRed = False:  Die Variable isRed wird beim Eintritt in die rote Fläche auf True gesetzt. So kann man vermeiden, dass der Roboterbeim Losfahren im roten Streifen sofort wieder anhält. isRed wird auf false gesetzt, sobald sich der Roboter auf einer gelben oder grünen Unterlage befindet

 


Aufgaben: Serie 7

1)

Erstelle eine Unterlage mit mehrern Farben und versuchen den Farbraum so anzupassen, dass der Roboter die Farben yellow, blue, green und black richtig erkennt.

Für die Simulation kannst du das Bild lighttest.gif verwenden, welches in der TigerJython -Distribution enthalten ist.

RobotContext.setStartPosition(250, 490)  
RobotContext.useBackground("sprites/lighttest.gif")


 

 




2)

Der Roboter soll mit Hilfe vom Farbsensor und den Farbigen Flächen möglichst effizient den Parcours abfahren.