Python‎ > ‎EV3 MicroPython‎ > ‎EV3 Python‎ > ‎

CASE STUDY: Project Soccer Robot

In Robocup, an attack robot will search for and find an IR Ball using an IR Sensor.

HiTech IR Sensor does not get recognised as an EV3 IR Sensor.
Only way is to use the Base Sensor class and this returns only one value:  direction ...

1 left - 5 center - 9 right

The mode seem to have an effect on accuracy and how wide an angle the IR sensor can "see".

I use a DC-ALL mode and that seems to work best for me (please tell me if you have any better ideas)

Modes

ModeDescriptionUnitsDecimalsNum. ValuesValues
DCDirection (unmodulated)none01value0: Direction (0 to 9) [12]
ACDirection (modulated)none01value0: Direction (0 to 9) [12]
DC-ALLAll values (unmodulated)none07

value0: Direction (0 to 9) [12]

value1: Sensor 1 signal strength (0 to 9) [12]

value2: Sensor 2 signal strength (0 to 9) [12]

value3: Sensor 3 signal strength (0 to 9) [12]

value4: Sensor 4 signal strength (0 to 9) [12]

value5: Sensor 5 signal strength (0 to 9) [12]

value6: Sensor mean (0 to 9) [12]

AC-ALLAll values (modulated)none06

value0: Direction (0 to 9) [12]

value1: Sensor 1 signal strength (0 to 9) [12]

value2: Sensor 2 signal strength (0 to 9) [12]

value3: Sensor 3 signal strength (0 to 9) [12]

value4: Sensor 4 signal strength (0 to 9) [12]

value5: Sensor 5 signal strength (0 to 9) [12]

To chase/hunt an IR Ball, I put together some sample code below:  
CAVEAT 1:  Please be aware, it does not know where the "goal" is in this code.  This I need to work out.

Possibly, I can use the Compass Sensor and work out how far from NORTH I have deviated and try and move back towards the the goal.

So trial and error is needed for this.

Also, I use EV3 MoveSteering function for the motors, this is ok, but it is not precise.   I might suggest using Move Tank for more precision.
see this useful blog explaining what Move Steering is and why Move Tank might be better:

CAVEAT 2: Additionally, since the HiTech IR Sensor is not the best, I cannot use the Proximity values to determine how close the IR ball is and moderate the speed accordingly. 

I will try and use the Ultrasonic Sensors for this, but there are so many obstacles...walls, other robots etc.  So which is the ball?
 

 

Interim Sample Code 1:
Please ignore functions that test US and IR sensors, look at the "soccer" function. 

#!/usr/bin/env python3
from time import sleep
from ev3dev2.led import Leds
from ev3dev.ev3 import *
from ev3dev2.sound import Sound
from ev3dev2.motor import MoveSteering  # , LargeMotor, MediumMotor
from ev3dev2.motor import OUTPUT_A, OUTPUT_D  # , OUTPUT_B, OUTPUT_C
from ev3dev2.sensor.lego import Sensor, UltrasonicSensor  # , InfraredSensor
from ev3dev2.sensor import INPUT_3, INPUT_4, INPUT_1, INPUT_2
import os

usL = UltrasonicSensor(INPUT_2)
usR = UltrasonicSensor(INPUT_1)
# ir = InfraredSensor(INPUT_4) #The Hi-Tech IR Sensor is not recognised
ir1 = Sensor(INPUT_4) # get BASE Sensor class instead
ir2 = Sensor(INPUT_3)
sound = Sound()
# a ampliture (volume) default 100
opts = '-a 200 -s 130 -v'
voice = 'en+m1'
os.system('setfont Lat15-TerminusBold14')
leds = Leds()


def talk(words):
    opts = '-a 200 -s 130 -v'
    try:
        if len(words) > 0:
            sound.speak(words, espeak_opts=opts+voice)
            print(words)
            words = ""
    except:
        words = "error: "+words
        sound.speak(words)
        print(words)

def getIRdir():
    global ir1, ir2
    ir1dir = ir1.value()  # returns direction 1-far right, 5-in front, 9-far left
    ir2dir = ir2.value()
    if ir1dir == ir2dir:
        return ir1dir
    if ir1dir == 0:
        return ir2dir
    if ir2dir == 0:
        return ir1dir
    if (ir1dir < ir2dir) and ir1dir < 5:
        return ir1dir
    if (ir2dir > ir1dir) and ir2dir > 5:
        return ir2dir
    return (ir1dir + ir2dir)/2


def testIR1():
    global ir1, ir2
    print(ir1.mode, ir2.mode)
    # DC, AC, DC-ALL, AC-ALL
    print(ir1.modes, ir2.modes)
    print(ir1.commands)


def testIR2(mode=""):
    global ir1, ir2
    if mode:
        ir1.mode = "DC-ALL"
        ir2.mode = "DC-ALL"
    while True:

        print(ir1.mode, '=', ir1.value(), ir2.mode,
              '=', ir2.value()">", getIRdir())
        # print(ir1.bin_data, ir2.bin_data)
        sleep(0.5)


def getUS():
    global usL, usR
    usdL = usL.distance_centimeters
    usdR = usR.distance_centimeters
    print("usL", usdL, "usR", usdR)
    return (usdL, usdR)


def fwd(dir=0):
    backd = MoveSteering(OUTPUT_D, OUTPUT_A)
    backd.on_for_seconds(steering=dir, speed=50, seconds=1)


def bwd(dir=0):
    backd = MoveSteering(OUTPUT_D, OUTPUT_A)
    backd.on_for_seconds(steering=dir, speed=-50, seconds=1)


def getSteering(direction):
    steering = {
        1: 100,
        2: 75,
        3: 50,
        4: 25,
        5: 0,
        6: -25,
        7: -50,
        8: -75,
        9: -100,
        0: -100
    }
    if direction in steering:
        stg = steering[direction]
    else:
        stg = 0
    return stg


def soccer():
    '''
    This is soccer attack mode.

    Input: IR direction of the IR ball
    Process: Determine the steering for the robot for MoveSteering command by looking up a dictionary
    Output: Drive the robot towards the IR ball using Steering 

    '''
    global leds
    talk("Welcome.  Soccer Robot demo is now starting")
    global ir1, ir2
    ir1.mode = "DC-ALL"
    ir2.mode = "DC-ALL"

    prev = 0
    while True:
        direction = getIRdir()
        stg = getSteering(direction)
        if direction == 0:
            if prev < stg:
                stg = -100
            else:
                stg = 100
        fwd(stg)

        prev = stg
        sleep(0.1)


def soccer2():
    pass


def demo2():
    '''
        Hunt mode   - like soccer robots use IR sensor to find ball
                    - but uses Ultrasonic (US) Sensor to prevent collision
    '''
    print("Decimals")
    print(ir1.decimals)
    print("Mode")
    print(ir1.mode)
    print("Modes")
    print(ir1.modes())
    # backd = MoveSteering(OUTPUT_D, OUTPUT_A)

    sleep(1.0)


def testUS():
    md = 40
    while True:
        (dl, dr) = getUS()
        if dl < md or dr < md:
            bwd()


# demo1()
# testIR1()
# testIR2(True)
# demo2()
soccer()




























Comments