Úloha „zastav se na čáře“ je velmi praktická.
Ostatně na herní plánu je několik čar, které můžete (ale nemusíte) k orientaci využít.
Lego má barevný senzor a k němu existuje Pybricks API .
Neuvědomil jsem si, že přesnost měření barvy bude záviset na okolním osvětlení a při použití hodnoty odrazivosti nebude černá nikdy nula (přece jen něco odrazí).
Chvilku jsem debugoval, jaké hodnoty naměřím na různých površích.
Nakonec jsem pro sebe použil hodnotu 20 (20 % odrazivosti).
A pak už se k výslednému programu dostaneme poměrně přímočaře.
V blocích to může vypadat takto.
V Pythonu takto.
# pybricks blocks file:{"blocks":{"languageVersion":0,"blocks":[{"type":"blockGlobalSetup","id":"bjK,wS1MYO7aiYkFSwd{","x":4,"y":51,"deletable":false,"next":{"block":{"type":"variables_set_prime_hub","id":"{)WuTTGMSJwLS.H*~PKI","extraState":{"optionLevel":1},"fields":{"VAR":{"id":"0ac8)M*M0@okqL6j*T]k"}},"inputs":{"AXIS_TOP":{"shadow":{"type":"blockParametersAxis","id":"G~~=qPiIM)z4Qy;ugq.J","fields":{"VALUE":"z"}}},"AXIS_FRONT":{"shadow":{"type":"blockParametersAxis","id":"=O,F=r_j:y!5C6~`*A2D","fields":{"VALUE":"y"}}}},"next":{"block":{"type":"variables_set_motor","id":"S?(a.C=~LVoJ~3YRo;}.","fields":{"VAR":{"id":"9-KY1{EjNJxUixuEoYJ?"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"pE~{$Zwzpz`i_VDqm^ab","fields":{"NAME":"A"}}},"POSITIVE_DIRECTION":{"shadow":{"type":"blockParametersDirection","id":"VrW-zLpmx[j,+8v+,L[1","fields":{"SELECTION":"Direction.COUNTERCLOCKWISE"}}}},"next":{"block":{"type":"variables_set_motor","id":"3,Y?*Mn1@v9fJ`yYW6Sf","fields":{"VAR":{"id":"@(Mc?VKF9P+IVA!,)0R;"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"r`9bbROX1dwatV7O$.:`","fields":{"NAME":"E"}}},"POSITIVE_DIRECTION":{"shadow":{"type":"blockParametersDirection","id":"Fk;M%s,~BY}0ww1j30bP","fields":{"SELECTION":"Direction.CLOCKWISE"}}}},"next":{"block":{"type":"variables_set_motor","id":"^b]cQj|TmdV%cZJhl0gI","fields":{"VAR":{"id":"#~*U;Y3)}OaA),GbQ/cW"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"?.^x_gX%wU.Xv.#3wRPP","fields":{"NAME":"D"}}},"POSITIVE_DIRECTION":{"shadow":{"type":"blockParametersDirection","id":"0Np/F+n#MjwgBk{6MrPK","fields":{"SELECTION":"Direction.CLOCKWISE"}}}},"next":{"block":{"type":"variables_set_motor","id":"I#`Wxj%/1]|h{X+ZQ;3Y","fields":{"VAR":{"id":"xE_y9@2/n%+##W#h*hFj"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"j1eKhU`bdoHdh)~]Hl2b","fields":{"NAME":"C"}}},"POSITIVE_DIRECTION":{"shadow":{"type":"blockParametersDirection","id":"|$c/*_TuT!~8{cQFN{[f","fields":{"SELECTION":"Direction.CLOCKWISE"}}}},"next":{"block":{"type":"variables_set_drive_base","id":"B@6q{(N{H$OlQN@o(=#7","fields":{"VAR":{"id":"/@.Q%T4BjtqKCq7$UAbr"}},"inputs":{"VAR":{"shadow":{"type":"variables_get_motor_device","id":"h-`^(Zu#NTvZ*mW#2vcD","fields":{"VAR":{"id":"9-KY1{EjNJxUixuEoYJ?","name":"kolo leve","type":"Motor"}}}},"VAR2":{"shadow":{"type":"variables_get_motor_device","id":"CD5,af-R[yO,bE]-?Uf_","fields":{"VAR":{"id":"@(Mc?VKF9P+IVA!,)0R;","name":"kolo prave","type":"Motor"}}}},"VALUE0":{"shadow":{"type":"unit_distance","id":"GNgo@U(M|24Obsy~%4x{","fields":{"VALUE0":88}}},"VALUE1":{"shadow":{"type":"unit_distance","id":"cIT+~l^nylC1%}(,bsKB","fields":{"VALUE0":144}}}},"next":{"block":{"type":"variables_set_color_sensor","id":"0]Gny{r@pu-me0u.qL+H","extraState":{"optionLevel":0},"fields":{"VAR":{"id":"4q7cl%:FR{.%!.~b;=4j"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"HrOt9)|o*,]VPV8SDZ9E","fields":{"NAME":"B"}}}},"next":{"block":{"type":"variables_set_color_sensor","id":"x.AGwFp0|}^R*%F(%TcG","extraState":{"optionLevel":0},"fields":{"VAR":{"id":"^z-R_D5t#~Oky5)7@fjS"}},"inputs":{"PORT":{"shadow":{"type":"blockParametersPort","id":"I!+TlWLqzTDYY6^$uKdf","fields":{"NAME":"F"}}}}}}}}}}}}}}}}}}}}},{"type":"blockGlobalStart","id":"3tJe|AWl0baN(wH9a$@.","x":990,"y":44,"deletable":false,"next":{"block":{"type":"blockDriveBaseUseGyro","id":"W=Lm:RpeA}v?nKUf*^6.","fields":{"METHOD":"DRIVEBASE_USE_GYRO_TRUE"},"inputs":{"VAR":{"shadow":{"type":"variables_get_drive_base_device","id":"i{6(E*p~D3tY|M-^UtvG","fields":{"VAR":{"id":"/@.Q%T4BjtqKCq7$UAbr","name":"drive base","type":"DriveBase"}}}}},"next":{"block":{"type":"blockDriveBaseConfigure","id":"g3I/xPp1/oeRSee5-LA^","extraState":{"optionLevel":1},"fields":{"METHOD":"DRIVEBASE_STRAIGHT_SPEED"},"inputs":{"VAR":{"shadow":{"type":"variables_get_drive_base_device","id":"Z+6V|uC*Z3_Z4Pd$0di/","fields":{"VAR":{"id":"/@.Q%T4BjtqKCq7$UAbr","name":"drive base","type":"DriveBase"}}}},"ARG0":{"shadow":{"type":"unit_speed","id":"oc%m!QtUlj%nS}0wUkdH","fields":{"VALUE0":500}}}},"next":{"block":{"type":"blockFlowWhile","id":"^w![3wsmge-,nl%)9)_2","fields":{"MODE":"WHILE"},"inputs":{"BOOL":{"shadow":{"type":"blockLogicTrue","id":"|%RuaCQaVxPi_*BB*Hea"},"block":{"type":"blockLogicCompare","id":"0-l;i-(OX+f@B$[%Nv?7","fields":{"OP1":"GT"},"inputs":{"A":{"shadow":{"type":"blockMathNumber","id":"0R9k4vfG#^mUZ#xuV!Yy","fields":{"NUM":3}},"block":{"type":"blockLightReflection","id":"xPaTrirocgrfw:z($hfN","inputs":{"VAR":{"shadow":{"type":"variables_get_light_intensity_device","id":"DOR_9uhk=S}7mpH~6ny:","fields":{"VAR":{"id":"4q7cl%:FR{.%!.~b;=4j","name":"senzor levy","type":"ColorSensor"}}}}}}},"B":{"shadow":{"type":"blockMathNumber","id":"=Fis}(OW{eVsQ%GL+Xv?","fields":{"NUM":20}}}}}},"DO":{"block":{"type":"blockDriveBaseDrive2","id":"e!qh#u{yRC]5T}d88!wD","extraState":{"optionLevel":2},"fields":{"METHOD":"DRIVEBASE_DRIVE_STRAIGHT"},"inputs":{"VAR":{"shadow":{"type":"variables_get_drive_base_device","id":"Fn3J0txHNG:z99+vK!pI","fields":{"VAR":{"id":"/@.Q%T4BjtqKCq7$UAbr","name":"drive base","type":"DriveBase"}}}},"ARG0":{"shadow":{"type":"unit_distance","id":"Zf;zZ*m@T_Mm5%_U]r.u","fields":{"VALUE0":50}}},"ARG1":{"shadow":{"type":"parameters_stop_4","id":"m4%XtpLADnb=l]x@*bmt","fields":{"VALUE":"Stop.NONE"}}}}}}},"next":{"block":{"type":"blockDriveBaseStop","id":"FQcgVD9TN#4W;ib{Q}Dj","inputs":{"VAR":{"shadow":{"type":"variables_get_drive_base_device","id":"sJ%~bnFg:!9s?/VX*/M(","fields":{"VAR":{"id":"/@.Q%T4BjtqKCq7$UAbr","name":"drive base","type":"DriveBase"}}}},"VALUE0":{"shadow":{"type":"parameters_stop_3","id":"ELOu@BWpK(Ie4(+d)AL_","fields":{"VALUE":"Stop.HOLD"}}}}}}}}}}}}}]},"variables":[{"name":"red","id":"^TRnlnrf1|b]54?=RSAE","type":"ColorDef"},{"name":"orange","id":"T/Ga=6s={mOa/4,vyj]{","type":"ColorDef"},{"name":"yellow","id":"z6p)=?w#+g|y@lU:VFt*","type":"ColorDef"},{"name":"green","id":"PQR$ys-f%#*T_4`Rx0fH","type":"ColorDef"},{"name":"cyan","id":"n3GEOv6@N!|xg_x}=GL+","type":"ColorDef"},{"name":"blue","id":"G_|mnBi;ov8st$C/z;$W","type":"ColorDef"},{"name":"violet","id":"MMX}YsyH/D)kVHpH2a/t","type":"ColorDef"},{"name":"magenta","id":"@4TT%Ad^Qyn!IQ9HhF{H","type":"ColorDef"},{"name":"white","id":"Yknl*y[~$s;/3RGi{ju1","type":"ColorDef"},{"name":"none","id":"e|_}L8nQoa5[!)|??9+L","type":"ColorDef"},{"name":"prime hub","id":"0ac8)M*M0@okqL6j*T]k","type":"PrimeHub"},{"name":"drive base","id":"/@.Q%T4BjtqKCq7$UAbr","type":"DriveBase"},{"name":"kolo leve","id":"9-KY1{EjNJxUixuEoYJ?","type":"Motor"},{"name":"kolo prave","id":"@(Mc?VKF9P+IVA!,)0R;","type":"Motor"},{"name":"motor predni","id":"#~*U;Y3)}OaA),GbQ/cW","type":"Motor"},{"name":"motor zadni","id":"xE_y9@2/n%+##W#h*hFj","type":"Motor"},{"name":"motor","id":"4f^oLh]vR?;f9cEyqLvm","type":"Motor"},{"name":"senzor levy","id":"4q7cl%:FR{.%!.~b;=4j","type":"ColorSensor"},{"name":"senzor pravy","id":"^z-R_D5t#~Oky5)7@fjS","type":"ColorSensor"},{"name":"sensor","id":"-BWH)YE(r`_KzM)7#.kx","type":"ColorSensor"}],"info":{"type":"pybricks","version":"1.3.2"}}
from pybricks.hubs import PrimeHub
from pybricks.parameters import Axis, Direction, Port, Stop
from pybricks.pupdevices import ColorSensor, Motor
from pybricks.robotics import DriveBase
# Set up all devices.
prime_hub = PrimeHub(top_side=Axis.Z, front_side=Axis.Y)
senzor_levy = ColorSensor(Port.B)
senzor_pravy = ColorSensor(Port.F)
kolo_leve = Motor(Port.A, Direction.COUNTERCLOCKWISE)
kolo_prave = Motor(Port.E, Direction.CLOCKWISE)
motor_predni = Motor(Port.D, Direction.CLOCKWISE)
motor_zadni = Motor(Port.C, Direction.CLOCKWISE)
drive_base = DriveBase(kolo_leve, kolo_prave, 88, 144)
# The main program starts here.
drive_base.use_gyro(True)
drive_base.settings(straight_speed=500)
while senzor_levy.reflection() > 20:
drive_base.straight(50, then=Stop.NONE)
drive_base.straight(0)
Pybricks nabízí pokročilejší funkce oproti Lego Spike prostředí.
Varianta psaní v Pythonu je zdarma, za grafické bloky si připlatíte.
Spouštění programů ve fyzickém světě dokáže vždycky něčím překvapit, třeba zjištěním, že i černá barva odrazí nějaké světlo.