片山 峻佑
Created October 21, 2019 © GPL3+

killer and prey

Now, AI robot start moving and chasing you. What you have to do is just telling a prey how to escape, of course, through Alexa.

BeginnerFull instructions provided4 hours135

Things used in this project

Story

Read more

Custom parts and enclosures

mycar.lxf

instruction for LEGO

Q_table.csv

place in the same hierarchy as server_alexa.py is

Code

model.json

JSON
changed a little bit from original one you can download, but do not use this change in this project.
{
  "interactionModel": {
    "languageModel": {
      "invocationName": "mindstorms",
      "intents": [{
          "name": "AMAZON.CancelIntent",
          "samples": []
        },
        {
          "name": "AMAZON.HelpIntent",
          "samples": []
        },
        {
          "name": "AMAZON.StopIntent",
          "samples": []
        },
        {
          "name": "AMAZON.NavigateHomeIntent",
          "samples": []
        },
        {
          "name": "MoveIntent",
          "slots": [{
              "name": "Direction",
              "type": "DirectionType"
            },
            {
              "name": "Duration",
              "type": "AMAZON.NUMBER"
            }
          ],
          "samples": [
            "{Direction} now",
            "{Direction} {Duration} seconds",
            "move {Direction} for {Duration} seconds"
          ]
        },
        {
          "name": "SetSpeedIntent",
          "slots": [{
            "name": "Speed",
            "type": "AMAZON.NUMBER"
          }],
          "samples": [
            "set speed {Speed} percent",
            "set {Speed} percent speed",
            "set speed to {Speed} percent"
          ]
        },
        {
          "name": "SetCommandIntent",
          "slots": [{
            "name": "Command",
            "type": "CommandType"
          }],
          "samples": [
            "activate {Command} mode",
            "move in a {Command}",
            "fire {Command}",
            "activate {Command}",
            "turn {Command}"
          ]
        }
      ],
      "types": [{
          "name": "DirectionType",
          "values": [{
              "name": {
                "value": "brake"
              }
            },
            {
              "name": {
                "value": "go backward"
              }
            },
            {
              "name": {
                "value": "go forward"
              }
            },
            {
              "name": {
                "value": "go right"
              }
            },
            {
              "name": {
                "value": "go left"
              }
            },
            {
              "name": {
                "value": "right"
              }
            },
            {
              "name": {
                "value": "left"
              }
            },
            {
              "name": {
                "value": "backwards"
              }
            },
            {
              "name": {
                "value": "backward"
              }
            },
            {
              "name": {
                "value": "forwards"
              }
            },
            {
              "name": {
                "value": "forward"
              }
            }
          ]
        },
        {
          "name": "CommandType",
          "values": [{
              "name": {
                "value": "circle"
              }
            },
            {
              "name": {
                "value": "square"
              }
            },
            {
              "name": {
                "value": "patrol"
              }
            },
            {
              "name": {
                "value": "cannon"
              }
            },
            {
              "name": {
                "value": "all shot"
              }
            },
            {
              "name": {
                "value": "one shot"
              }
            }
          ]
        }
      ]
    }
  }
}

main.py

Python
#!/usr/bin/env pybricks-micropython

import sys
import socket
import motion_module
from pybricks import ev3brick as brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor,
                                 InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import (Port, Stop, Direction, Button, Color,
                                 SoundFile, ImageFile, Align)
from pybricks.tools import print, wait, StopWatch
from pybricks.robotics import DriveBase

#Motor
motor_l = Motor(Port.D)
motor_r = Motor(Port.A)

#Sensor
color_l = ColorSensor(Port.S4)
color_r = ColorSensor(Port.S1)
touch = TouchSensor(Port.S2)

#error
def error_exit(err_str):
    print(err_str, file=sys.stderr)
    sys.exit(1)

#client
def client():
    # make client socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # connect to server
    #use IP address and port of server
    host = '127.0.0.1'
    port = 40000
    bufsize = 1
    if s.connect((host, port)) == -1:
        error_exit('Error: client_p.connect')

    # first : receive the action
    # second : act in practice
    # finally : send the signal of end of action
    while True:
        # receive the action from server
        act = s.recv(bufsize)
        if act == -1:
            error_exit('Error: client_p.recv')

        # at the end of game
        if act.decode() == '':
            break

        act = int(act.decode())
        # robot acts in practice
        motion_module.adjust_position(color_l, color_r, motor_l, motor_r)
        motion_module.move(act, color_l, color_r, motor_l, motor_r, touch)

        # send the signal to server to tell the end of action
        if s.send(str(act).encode()) == -1:
            error_exit('Error: client_p.send')

client()

motion_module.py

Python
motion library for killer
#!/usr/bin/env pybricks-micropython

from pybricks import ev3brick as brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor,
                                 InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import (Port, Stop, Direction, Button, Color,
                                 SoundFile, ImageFile, Align)
from pybricks.tools import print, wait, StopWatch
from pybricks.robotics import DriveBase


# trace WHITE line and stop RED point
# WHITE : course  RED : lattice point  BLACK : outside

# action ( 0 : go straight, 1 : turn left, 2 :turn right 3 : stay )
def move(action, color_l, color_r, motor_l, motor_r, touch):
    if action == 0:
        trace_line(color_l, color_r, motor_l, motor_r, touch)
    elif action == 1:
        turn_l(color_l, color_r, motor_l, motor_r)
    elif action == 2:
        turn_r(color_l, color_r, motor_l, motor_r)
    elif action == 3:
        pass
    else:
        print("move error")
        exit(1)

# car moves until RED point
def trace_line(color_l, color_r, motor_l, motor_r, touch):
    while  color_l.color() != Color.RED and color_r.color() != Color.RED :
        if touch.pressed() :    # when touch sensor is pressed, stop moving
            break
        sl = 300                # speed left and right
        sr = 300
        if color_l.color() == Color.BLACK: 
            sr /= 3
        if color_r.color() == Color.BLACK:
            sl /= 3

        t = 350
        motor_l.run_time(sl, t, Stop.COAST, False)
        motor_r.run_time(sr, t, Stop.COAST, True)

# turn left
def turn_l(color_l, color_r, motor_l, motor_r) :
    spd = 200
    tim = 150
    tim2 = 150
    while color_l.color() == Color.WHITE:
        motor_l.run_time(-spd, tim, Stop.COAST, False)
        motor_r.run_time(spd, tim, Stop.COAST, True)
    motor_l.run_time(-spd, 1.5*tim, Stop.COAST, False)
    motor_r.run_time(spd, 1.5*tim, Stop.COAST, True)
    while color_l.color() == Color.BLACK :
        motor_l.run_time(-spd, tim, Stop.COAST, False)
        motor_r.run_time(spd, tim, Stop.COAST, True)
    while color_r.color() == Color.BLACK :
        motor_l.run_time(-spd, tim, Stop.COAST, False)
        motor_r.run_time(spd, tim, Stop.COAST, True)
    motor_l.run_time(-spd, tim2, Stop.COAST, False)
    motor_r.run_time(spd, tim2, Stop.COAST, True)

# turn right
def turn_r(color_l, color_r, motor_l, motor_r) :
    spd = 200
    tim = 150
    tim2 = 150
    while color_r.color() == Color.WHITE:
        motor_l.run_time(spd, tim, Stop.COAST, False)
        motor_r.run_time(-spd, tim, Stop.COAST, True)
    motor_l.run_time(spd, 1.5*tim, Stop.COAST, False)
    motor_r.run_time(-spd, 1.5*tim, Stop.COAST, True)
    while color_r.color() == Color.BLACK :
        motor_l.run_time(spd, tim, Stop.COAST, False)
        motor_r.run_time(-spd, tim, Stop.COAST, True)
    while color_l.color() == Color.BLACK :
        motor_l.run_time(spd, tim, Stop.COAST, False)
        motor_r.run_time(-spd, tim, Stop.COAST, True)
    motor_l.run_time(spd, tim2, Stop.COAST, False)
    motor_r.run_time(-spd, tim2, Stop.COAST, True)
    
# adjust position
def adjust_position(color_l, color_r, motor_l, motor_r):
    spd = 200
    tim0 = 150
    tim1 = 450
    if color_l.color() == Color.RED or color_r.color() == Color.RED:
        while color_l.color() == Color.RED or color_r.color() == Color.RED:
            motor_l.run_time(spd, tim0, Stop.COAST, False)
            motor_r.run_time(spd, tim0, Stop.COAST, True)
        
        motor_l.run_time(spd, tim1, Stop.COAST, False)
        motor_r.run_time(spd, tim1, Stop.COAST, True)

server_alexa.py

Python
# server used when prey is controlled by human'sinstructions with alexa

import sys
import socket
import threading
import random
import csv

# byte per socket communication 
bufsize = 1

# [x, y, direction]
# 0 <= x, y <= 4,  direction[0:>  1:^  2:<  3:v]
state_hun = [4, 0, 1]
state_pre = [0, 4, 3]

# action 0 : go, 1 : turn left, 2 :turn right
Q_table = [[[[[[[0 for act in range(4)] for me_x in range(5)] for me_y in range( \
    5)] for op_x in range(5)] for op_y in range(5)] for me_dir in range(4)] for op_dir in range(4)]

# error
def error_exit(err_str):
    print(err_str, file=sys.stderr)
    sys.exit(1)

# rebuilding QTable from array
def make_Q_table(row, table_number):
    for i in range(4):  # op_dir
        for j in range(4):  # me_dir
            for a in range(5):  # op_y
                for b in range(5):  # op_x
                    for c in range(5):  # me_y
                        for d in range(5):  # me_x 
                            for k in range(4):
                                value = k + d * 4 + c * 4 * 5 + b * 4 * 5 * 5 + \
                                a * 4 * 5 * 5 * 5 + j * 4 * 5 * 5 * 5 * 5 + i * 4 * 5 * 5 * 5 * 5 * 4
                                if table_number == 1:
                                    Q_table[i][j][a][b][c][d][k] = float(row[value])
                                elif table_number == -1:
                                    Q_table_escape[i][j][a][b][c][d][k] = row[value]

# opne csv file of array of Q value
def openfile(path, table_number):
    with open(path) as fp:
        reader = csv.reader(fp)
        for row in reader:
            make_Q_table(row, table_number)

# decide hunter's action
# hunter acts according to max value of QTalbe
def decide_move():
    action = -1
    max_Q = -100
    for k in range(3):
        tmp_Q = Q_table[state_pre[2]][state_hun[2]][state_pre[1] \
                                                    ][state_pre[0]][state_hun[1]][state_hun[0]][k]
        if tmp_Q > max_Q:
            max_Q = tmp_Q
            action = k

    return action

# change the state of hunter from current state and action
def change_state_hunter(act) :
    dir = state_hun[2]
    if act == 0 :
        if dir == 0 :
            state_hun[0] += 1
        elif dir == 1 :
            state_hun[1] += 1
        elif dir == 2 :
            state_hun[0] -= 1
        else :
            state_hun[1] -= 1
    elif act == 1 :
        state_hun[2] = (state_hun[2]+1) % 4
    elif act == 2 :
        state_hun[2] = (state_hun[2]-1) % 4

# function to communicate with prey
# argument is socket of prey
def escape(sp) :
    # first : receive the action from prey
    # second : change state of prey
    while state_hun[:2] != state_pre[:2] :
        # get the signal and change the state of prey
        act = sp.recv(bufsize)
        if act == -1 :
            error_exit('Error: server.recv from prey')
        
        # decode and change (char -> int)
        act = int(act.decode())
        print('prey : ', act) #test
        # change the state of prey according to action
        change_state_prey(act)

    # close socket of prey
    if sp.close() == -1 :
        error_exit('Error: server_p.close')



# main function of server
def server() :
    # make QTable from csv.file
    openfile('./Q_table.csv',1)
    
    # make server socket
    ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    if ss == -1 :
        error_exit('Error: socket.socket')

    # assign IP address and port num
    host = '127.0.0.1'
    port = 40000
    if ss.bind((host, port)) == -1 :
        error_exit('Error: socket.bind')

    # the number of client
    if ss.listen(2) == -1 :
        error_exit('Error: server.bind')

    # wait the connection from prey client
    print('please start prey')
    prey, (cli_add_p, cli_port_p) = ss.accept()
    if prey == -1 : 
        error_exit('Error: server.accept of prey')
    # make thread to communicate with prey
    threadp = threading.Thread(target = escape, args = (prey,) )
    threadp.start()
    
    # wait the connection from hunter client
    print('please start hunter')
    hunter, (cli_add_h, cli_port_h) = ss.accept()
    if hunter == -1 : 
        error_exit('Error: server.accept of hunter')

    # don't accept the connection from now
    if ss.close() == -1 :
        error_exit('Error: server.close')

    print('game start')

    # loop of hunter
    # first : decide hunter's action
    # second : send it to hunter
    # third : receive the signal of the end of robot's action
    # last : change hunter's state
    while state_hun[:2] != state_pre[:2] :
        # select action of hunter
        act = decide_move()
    
        print('hunter : ', act) #test
        # send action to hunter
        if hunter.send(str(act).encode()) == -1 :
            error_exit('Error: server.send to prey')
        
        # get the signal and change the state of hunter
        if hunter.recv(bufsize) == -1 :
            error_exit('Error: server.recv from prey')
        change_state_hunter(act)

    # close socket of hunter
    if hunter.close() == -1 :
        error_exit('Error: server_p.close')


server()

mission-03.py

Python
# Copyright 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
#
# You may not use this file except in compliance with the terms and conditions
# set forth in the accompanying LICENSE.TXT file.
#
# THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY DISCLAIMS, WITH
# RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
# THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.

import time
import logging
import json
import random
import threading
import alexa_move
import sys
import socket

from enum import Enum
from agt import AlexaGadget

from ev3dev2.led import Leds
from ev3dev2.sound import Sound
from ev3dev2.motor import OUTPUT_A, OUTPUT_B, OUTPUT_D, MoveTank, SpeedPercent, MediumMotor

# Set the logging level to INFO to see messages from AlexaGadget
logging.basicConfig(level=logging.INFO)

# socket


def error_exit(err_str):
    print(err_str, file=sys.stderr)
    sys.exit(1)


def client_connect():
    # make client socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # connect to server
    host = '*********'
    port = 40000
    if s.connect((host, port)) == -1:
        error_exit('Error: client_p.connect')
    return s


def client_send(act):
    # send the signal to server
    if s.send(str(act).encode()) == -1:
        error_exit('Error: client_p.send')


class Direction(Enum):
    """
    The list of directional commands and their variations.
    These variations correspond to the skill slot values.
    """
    FORWARD = ['forward', 'forwards', 'go forward']
    BACKWARD = ['back', 'backward', 'backwards', 'go backward']
    LEFT = ['left', 'go left']
    RIGHT = ['right', 'go right']
    STOP = ['stop', 'brake']


class Command(Enum):
    """
    The list of preset commands and their invocation variation.
    These variations correspond to the skill slot values.
    """
    MOVE_CIRCLE = ['circle', 'spin']
    MOVE_SQUARE = ['square']
    PATROL = ['patrol', 'guard mode', 'sentry mode']
    FIRE_ONE = ['cannon', '1 shot', 'one shot']
    FIRE_ALL = ['all shot']
    LEFT = ['left']
    RIGHT = ['right']


class MindstormsGadget(AlexaGadget):
    """
    A Mindstorms gadget that performs movement based on voice commands.
    Two types of commands are supported, directional movement and preset.
    """

    def __init__(self):
        """
        Performs Alexa Gadget initialization routines and ev3dev resource allocation.
        """
        super().__init__()

        # Gadget state
        self.patrol_mode = False

        # Ev3dev initialization
        self.leds = Leds()
        self.sound = Sound()
        self.drive = MoveTank(OUTPUT_A, OUTPUT_D)
        self.weapon = MediumMotor(OUTPUT_B)

        # Start threads
        threading.Thread(target=self._patrol_thread, daemon=True).start()

    def on_connected(self, device_addr):
        """
        Gadget connected to the paired Echo device.
        :param device_addr: the address of the device we connected to
        """
        self.leds.set_color("LEFT", "GREEN")
        self.leds.set_color("RIGHT", "GREEN")
        print("{} connected to Echo device".format(self.friendly_name))

    def on_disconnected(self, device_addr):
        """
        Gadget disconnected from the paired Echo device.
        :param device_addr: the address of the device we disconnected from
        """
        self.leds.set_color("LEFT", "BLACK")
        self.leds.set_color("RIGHT", "BLACK")
        print("{} disconnected from Echo device".format(self.friendly_name))

    def on_custom_mindstorms_gadget_control(self, directive):
        """
        Handles the Custom.Mindstorms.Gadget control directive.
        :param directive: the custom directive with the matching namespace and name
        """
        try:
            payload = json.loads(directive.payload.decode("utf-8"))
            print("Control payload: {}".format(payload))
            control_type = payload["type"]
            if control_type == "move":

                # Expected params: [direction, duration, speed]
                self._move(payload["direction"], int(
                    payload["duration"]), int(payload["speed"]))

            if control_type == "command":
                # Expected params: [command]
                self._activate(payload["command"])

        except KeyError:
            print("Missing expected parameters: {}".format(directive))

    def _move(self, direction, duration: int, speed: int, is_blocking=False):
        """
        Handles move commands from the directive.
        Right and left movement can under or over turn depending on the surface type.
        :param direction: the move direction
        :param duration: the duration in seconds
        :param speed: the speed percentage as an integer
        :param is_blocking: if set, motor run until duration expired before accepting another command
        """
        print("Move command: ({}, {}, {}, {})".format(
            direction, speed, duration, is_blocking))
        if direction in Direction.FORWARD.value:
            # self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(
                # speed), duration, block=is_blocking)

            # *******************************************************************
            alexa_move.move(0)
            alexa_move.adjust_position()
            client_send(0)

        if direction in Direction.LEFT.value:

            alexa_move.move(1)
            alexa_move.adjust_position()                                        # changed
            client_send(1)

        if direction in Direction.RIGHT.value:

            alexa_move.move(2)
            alexa_move.adjust_position()
            client_send(2)
            # ***********************************************************************

        if direction in Direction.BACKWARD.value:
            self.drive.on_for_seconds(
                SpeedPercent(-speed), SpeedPercent(-speed), duration, block=is_blocking)
        '''
        if direction in (Direction.RIGHT.value + Direction.LEFT.value):
            self._turn(direction, speed)
            self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(
                speed), duration, block=is_blocking)
        '''
        if direction in Direction.STOP.value:
            self.drive.off()
            self.patrol_mode = False

    def _activate(self, command, speed=50):
        """
        Handles preset commands.
        :param command: the preset command
        :param speed: the speed if applicable
        """
        print("Activate command: ({}, {})".format(command, speed))
        if command in Command.MOVE_CIRCLE.value:
            self.drive.on_for_seconds(SpeedPercent(
                int(speed)), SpeedPercent(5), 12)

        if command in Command.MOVE_SQUARE.value:
            for i in range(4):
                self._move("right", 2, speed, is_blocking=True)

        if command in Command.PATROL.value:
            # Set patrol mode to resume patrol thread processing
            self.patrol_mode = True

        if command in Command.FIRE_ONE.value:
            print("called")
            #self.weapon.on_for_rotations(SpeedPercent(100), 3)
            alexa_move.move(2)

        if command in Command.FIRE_ALL.value:
            self.weapon.on_for_rotations(SpeedPercent(100), 10)

        if command in Command.LEFT.value:
            self.drive.on_for_seconds(SpeedPercent(0), SpeedPercent(speed), 2)
        if command in Command.RIGHT.value:
            self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(0), 2)

    def _turn(self, direction, speed):
        """
        Turns based on the specified direction and speed.
        Calibrated for hard smooth surface.
        :param direction: the turn direction
        :param speed: the turn speed
        """
        if direction in Direction.LEFT.value:
            self.drive.on_for_seconds(SpeedPercent(0), SpeedPercent(speed), 2)

        if direction in Direction.RIGHT.value:
            self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(0), 2)

    def _patrol_thread(self):
        """
        Performs random movement when patrol mode is activated.
        """
        while True:
            while self.patrol_mode:
                print("Patrol mode activated randomly picks a path")
                direction = random.choice(list(Direction))
                duration = random.randint(1, 5)
                speed = random.randint(1, 4) * 25

                while direction == Direction.STOP:
                    direction = random.choice(list(Direction))

                # direction: all except stop, duration: 1-5s, speed: 25, 50, 75, 100
                self._move(direction.value[0], duration, speed)
                time.sleep(duration)
            time.sleep(1)


if __name__ == '__main__':

    # Startup sequence
    gadget = MindstormsGadget()
    gadget.sound.play_song((('C4', 'e'), ('D4', 'e'), ('E5', 'q')))
    gadget.leds.set_color("LEFT", "GREEN")
    gadget.leds.set_color("RIGHT", "GREEN")
    s = client_connect()

    # Gadget main entry point
    alexa_move.adjust_position()
    gadget.main()

    # Shutdown sequence
    gadget.sound.play_song((('E5', 'e'), ('C4', 'e')))
    gadget.leds.set_color("LEFT", "BLACK")
    gadget.leds.set_color("RIGHT", "BLACK")

Alexa_move.py

Python
from ev3dev2.motor import LargeMotor, OUTPUT_A, OUTPUT_C, SpeedPercent, MoveTank, Motor, OUTPUT_D
from ev3dev2.sensor import INPUT_1, INPUT_2, INPUT_4
from ev3dev2.sensor.lego import GyroSensor, ColorSensor
from ev3dev2.led import Leds
from ev3dev2.sound import Sound

# Motor
motor_l = Motor(OUTPUT_D)
motor_r = Motor(OUTPUT_A)

# Sensor

color_l = ColorSensor(INPUT_4)
color_r = ColorSensor(INPUT_1)


def judge_red(color):
    if color.color == ColorSensor.COLOR_RED:
        return True
    else:
        return False


def judge_white(color):
    if color.color == ColorSensor.COLOR_WHITE:
        return True
    else:
        return False

# call function referring argument
# 0...go forward now, 1...go left now, 2...go right now


def move(action):
    if action == 0:
        trace_line()
    elif action == 1:
        turn_l()
    elif action == 2:
        turn_r()
    else:
        print("move error")
        exit(1)

# until colorsensor detect red, keep going
# if the direction of robot is incorrect, fix direction.


def trace_line():
    while color_l.color != ColorSensor.COLOR_RED and color_r.color != ColorSensor.COLOR_RED:
        print(color_r, color_l)
        tank_drive = MoveTank(OUTPUT_A, OUTPUT_D)
        sl = 20
        sr = 20
        if color_l.color == 1:
            sr /= 3
        if color_r.color == 1:
            sl /= 3
        tank_drive.on_for_seconds(SpeedPercent(sr), SpeedPercent(sl), 0.5)


# turn right about 90 degree


def turn_r():
    spd = 10
    tim = 0.15
    tank_drive = MoveTank(OUTPUT_A, OUTPUT_D)

    while color_r.color == ColorSensor.COLOR_WHITE:
        tank_drive.on_for_seconds(SpeedPercent(-spd), SpeedPercent(spd), tim)

    tank_drive.on_for_seconds(SpeedPercent(-spd), SpeedPercent(spd), tim)

    while color_r.color == ColorSensor.COLOR_BLACK:
        tank_drive.on_for_seconds(SpeedPercent(-spd), SpeedPercent(spd), tim)

    while color_l.color == ColorSensor.COLOR_BLACK:
        tank_drive.on_for_seconds(SpeedPercent(-spd), SpeedPercent(spd), tim)

    tank_drive.on_for_seconds(SpeedPercent(-spd), SpeedPercent(spd), tim)

# turn left about 90 degree


def turn_l():

    spd = 10
    tim = 0.15
    tank_drive = MoveTank(OUTPUT_A, OUTPUT_D)

    while color_l.color == ColorSensor.COLOR_WHITE:
        tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(-spd), tim)

    tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(-spd), tim * 1.5)

    while color_l.color == ColorSensor.COLOR_BLACK:
        tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(-spd), tim)

    while color_r.color == ColorSensor.COLOR_BLACK:
        tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(-spd), tim)

    tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(-spd), tim)

# After detecting red, adjust position to place the body of robot in the center of red square.


def adjust_position():
    spd = 10
    tim0 = 0.15
    tim1 = 0.75
    tank_drive = MoveTank(OUTPUT_A, OUTPUT_D)
    if color_l.color == ColorSensor.COLOR_RED or color_r.color == ColorSensor.COLOR_RED:
        while color_l.color == ColorSensor.COLOR_RED or color_r.color == ColorSensor.COLOR_RED:
            tank_drive.on_for_seconds(
                SpeedPercent(spd), SpeedPercent(spd), tim0)

        tank_drive.on_for_seconds(SpeedPercent(spd), SpeedPercent(spd), tim1)

Credits

片山 峻佑

片山 峻佑

3 projects • 2 followers

Comments