โš’๏ธLesson 4: Event skills

Aim

The aim of this lesson is to learn how to make Misty more aware of her surroundings using event-based skills. By the end of the lesson, you will be able to build basic skills in Python and utilize most of Misty's sensory capabilities to create more complex social interactions with your robot character.

Defining Events

Challenge 1: Import, register and define an event

You've probably already discovered in Blockly all the fun interactions you can build using Misty's capacitive touch and bump sensors. Now let's try building them in Python!

To use events in Python you will need to import the relevant library that contains all the events that Misty can trigger. This library works as any other library in Python and itโ€™s called โ€œmistyPy.Eventsโ€, it contains the APIs for your events such as BumpSensors, Facerecognition, ARTagdetection etc. You can find out more about them in the Events section in Python Elements. Let's start with importing the library.

from mistyPy.Robot import Robot #libraries
from mistyPy.Events import Events

Once you've imported this library the next step is to register the event you want in your code using the misty.register_event API. To have Misty continously monitor her sensors you can use the equivalent to the Run Until Stopped block in Blockly called misty.keep_alive.

from mistyPy.Robot import Robot #libraries
from mistyPy.Events import Events

#events definitions
misty.register_event(event_name='bump_event', event_type=Events.BumpSensor, callback_function=bumped, keep_alive=False)

#"run until stopped" of blockly
misty.keep_alive()

In the first parameter you need to insert the the name of the event you want to use. The second parameter identifies which event in that category you want to trigger. You need to use one of the names provided in Events. The third parameter is the callback function which contains the name of the function you need to use to define which commands Misty should execute when an event is triggered. The last parameter is keep_alive, if you set it to โ€œFalseโ€, once your event has been triggered the code will stop, instead, if you set it to โ€œTrueโ€ you can decide when to stop your code by clicking the Stop button. In the default line, the last parameter is set as False.

Finally, the third step is to define and create the sensor functions associated with your event using def function_name(data) and print(data) . This can be placed between your library import and the registered event. For your sequence to be contained within the function you need to place it after print(data).

from mistyPy.Robot import Robot #libraries
from mistyPy.Events import Events

#function
def bumped(data):   
    print(data)
    # Function code here
    # You can have multiple lines of code inside the function
    # The function's logic goes here

#events definitions
misty.register_event(event_name='bump_event', event_type=Events.BumpSensor, callback_function=bumped, keep_alive=False)

#"run until stopped" of blockly
misty.keep_alive()

Event skills

Challenge 2: Python event skills with a human touch

Great work! Now that you've successfully created a template for your event, you can start building event based skills in Python for your robot character using the skill tree concept that we covered in Blockly Lessons. Human touch, like a handshake or pat on the back, is an important element to social interactions, and human-robot interactions are no exception.

Using the template you created, you can now register other events such as the capacitive touch sensor event in the example below. When you are building functions you can choose to specify which sensors you want to use from a group, if you don't specify the sensor Misty will trigger the function when any of the sensors in the group are triggered, similar to when you select โ€œanyโ€ when creating sensor events in Blockly. Let's try using all of the the movement and expression API calls you've learned so far to have Misty respond to your touch.

from mistyPy.Robot import Robot #libraries
from mistyPy.Events import Events

misty = Robot()

def bumped(data):   #functions
    print(data)
    misty.display_image("e_Love.jpg", 1)
    misty.move_head(0, -10, 0, 50)
    misty.move_arms(90, -70, 50, 50)
    misty.change_led(255, 0, 0)

def touched(data):
    print(data)
    misty.display_image("e_Joy.jpg", 1)
    misty.move_head(0, 0, 0, 50)
    misty.move_arms(-40, 90, 50, 50)
    misty.change_led(0, 255, 0)

#events definitions
misty.register_event(event_name='bumped', event_type=Events.BumpSensor, callback_function=bumped, keep_alive=True)
misty.register_event(event_name='touch', event_type=Events.TouchSensor, callback_function=touched, keep_alive=True)

#"run until stopped" of blockly
misty.keep_alive()

Challenge 3: Expand your event skill tree

Congratulations! You have built your first event skill tree in Python. Now you can grow your skill tree by creating more branches in your interaction with Misty using individual sensors in a group. To do this you will need to build a condition in your function that will help Misty verify which sensor to use.

For example in the bump sensor function, to select a specific bumper in the group you need to create a condition using an if statement where you specify which of them you want to use:

if data["message"]["sensorId"] == 'bfr':
#'bfr' is short for Front-Right Bumper

For the bump sensors and the touch sensor, you can use their name ID. You can find all the name ID's for the sensors in Sensor Events

When you create a condition it's always good practice to account for the possibility that it may not be verified due to syntax errors in your code. For example we can use an else statement to have Misty show a red light when something goes wrong.

from mistyPy.Robot import Robot
from mistyPy.Events import Events

misty = Robot()

def bumped(data):
    print(data)
    if data["message"]["sensorId"] == 'bfr': #condition
        misty.drive_time(0, -50, 8000)
        misty.change_led(0, 255, 255)
        time.sleep(1)
        misty.drive_time(30, 0, 5000)
        misty.change_led(255, 255, 0)
    else: #what happens if the condition is not verified
        misty.change_led(255,0,0)

def touched(data):
    print(data)
    if data["message"]["sensorPosition"] == 'HeadFront' :
        misty.change_led(0, 255, 0)
        misty.drive_time(30, 0, 5000)
        misty.display_image("e_EcstacyHilarious.jpg", 1)
    else:
        misty.change_led(255,0,0)

misty.register_event(event_name='touch', event_type=Events.TouchSensor, callback_function=touched, keep_alive=True)
misty.register_event(event_name='bumped', event_type=Events.BumpSensor, callback_function=bumped, keep_alive=True)

misty.keep_alive()

Challenge 4: Compact your event skill tree

As you grow your event skill tree you will find that your event functions can take up a lot of space. To save space and time try compacting your skill tree using the elif (else if) statement. This will allow you to contain all of the conditions for each sensor within a single function group as shown in the example below.

from mistyPy.Robot import Robot
from mistyPy.Events import Events

misty = Robot()

misty.speak("What's your favourite colour?", 1)
misty.move_head(0, 0, 20, 50)
misty.display_image("e_Contempt.jpg", 1)

def bumped(data): # function with more condition
    print(data)
    if data["message"]["sensorId"] == 'bfr':
        misty.change_led(0,0,255)
    elif data["message"]["sensorId"] == 'bfl':
        misty.change_led(255,0,0)
    elif data["message"]["sensorId"] == 'brr':
        misty.change_led(255,0,255)
    elif data["message"]["sensorId"] == 'brl':
        misty.change_led(0,255,0)
    else:
        misty.change_led(255,255,255)

misty.register_event(event_name='bumped', event_type=Events.BumpSensor, callback_function=bumped, keep_alive=True)

misty.keep_alive()

Event message

Challenge 5: Generalize your event skill tree

If you've worked with event messages in Blockly you may remember that it's an elegant way to compact and generalize your event skill. Instead of writing values in each condition within a function group, you can simply use an event message to return the value from the sensor that you have triggered. You can use the data from an event as strings in your code and make it more flexible and slim. Event messages can be used in a number of events such as Face Recognition, Object Recognition, BumpSensor, TouchSensors, etc. For example if we use the misty.speak API together with an event message we can have Misty say which of her touch sensors was triggered.

from mistyPy.Robot import Robot
from mistyPy.Events import Events

misty = Robot()

def touched(data):
    print(data)
    misty.speak("Hello there, this is my " +  data["message"]["sensorPosition"], 1)

misty.register_event(event_name='touch', event_type=Events.TouchSensor, callback_function=touched, keep_alive=True)
misty.keep_alive()

Up Next ๐Ÿ‘‡

๐Ÿ‘€pageLesson 5: Expand awareness

Last updated