pythonevent-handling

keyboard_trigger = Event() returns "NameError: name 'Event' is not defined"


I am trying to write a simple "Object avoidance" program for my robot.

The initial version works, but when I try to exit with a Ctrl-C, the program halts but the robot keeps moving until I physically turn it off.

I'm trying to use a trick that was used in a different program that listens for keyboard events and then stops the robot when one is detected.

The code that I am having difficulty with:

# Object Avoidance Robot
# Drives in a straight line untill it reaches an obsticle within "X" cm.
# It then stops, backs up a few cm, turns a random amount, and then proceeds.

import easygopigo3 as easy
import time
import random
import signal
import os
import sys

gpg = easy.EasyGoPiGo3()
gpg = easy.EasyGoPiGo3()
servo_1 = gpg.init_servo('SERVO1')
servo_2 = gpg.init_servo('SERVO2')
sleep_time = 0.50  # pause time in seconds

my_distance_portI2C = gpg.init_distance_sensor('I2C')
time.sleep(0.1)

# for triggering the shutdown procedure when a signal is detected
keyboard_trigger = Event()
def signal_handler(signal, frame):
    print("Signal detected. Stopping threads.")
    gpg.stop()
    keyboard_trigger.set()

print("Running: Test Servos.\n")

# Read the connected robot's serial number
serial_number = gpg.get_id() # read and display the serial number

# For testing only - "invalid" serial number
# serial_number = "invalid"

print("This robot's serial number is\n"+serial_number+"\n")


# Servo constants for each robot

# Each robot is identified by its unique serial number

# Charlene:
if serial_number == "A0F6E45F4E514B4B41202020FF152B11":

# Charlene's servo constants
    print("Robot is \"Charlene\"")
    center_1 = 86  # Horizontal centering - smaller is further right.
    center_2 = 76  # Vertical centering - smaller is further up.

# Charlie:
elif serial_number == "64B61037514E343732202020FF111A05":

# Charlie's servo constants
    print("Robot is \"Charlie\"")
    center_1 = 86  # Horizontal centering - smaller is further right.
    center_2 = 90  # Vertical centering - smaller is further up.

else:
# Unknown serial number
    print("I don't know who robot", serial_number, "is,")
    print("If we got this far, it's obviously a GoPiGo robot")
    print("But I don't know what robot it is, so I'm using")
    print("the default centering constants of 90/90.\n")

# Default servo constants
    print("Robot is \"Unknown\"")
    print("Please record the robot's serial number, name,")
    print("and derived centering constants.")
    center_1 = 90
    center_2 = 90

# Start Test Servos

# Define excursions
right = center_1 - 45
left = center_1 + 45
up = center_2 - 45
down = center_2 + 45

def test_servos():
    # Test servos
    print("\nStarting test:")
    print("Using centering constants "+str(center_1)+"/"+str(center_2), "for this robot")

    print("\nCenter Both Servos")
    servo_1.rotate_servo(center_1)
    servo_2.rotate_servo(center_2)
    time.sleep(sleep_time)

    print("Test Servo 1 (horizontal motion)")
    servo_1.rotate_servo(right)
    time.sleep(sleep_time)
    servo_1.rotate_servo(left)
    time.sleep(sleep_time)
    servo_1.rotate_servo(center_1)
    time.sleep(sleep_time)

    print("Test Servo 2 (vertical motion)")
    servo_2.rotate_servo(up)
    time.sleep(sleep_time)
    servo_2.rotate_servo(down)
    time.sleep(sleep_time)

    print("Re-Center Both Servos")
    servo_1.rotate_servo(center_1)
    servo_2.rotate_servo(center_2)
    time.sleep(sleep_time)
    servo_1.disable_servo()
    servo_2.disable_servo()
    print("Complete: Test Servos - Exiting.")

def avoid():
    while True:
        while my_distance_portI2C.read_inches() > 20:
            gpg.forward()
            gpg.stop()
            time.sleep(1)
            gpg.backward()
            time.sleep(1)
            gpg.stop()
            test_servos()
            gpg.backward()
            time.sleep(4)
            gpg.stop()
            time.sleep(1)
            gpg.turn_degrees((random.randint(90, 270)), blocking=True)
            time.sleep(1) # slowdown


#------------------------------------
# Main routine entry point is here
#------------------------------------

if __name__ == "__main__":
    # registering both types of termination signals
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

test_servos()  # make sure servos are centered
avoid()
logging.info("Finished!")
sys.exit(0)
while not keyboard_trigger.is_set():
    sleep(0.25)

# until some keyboard event is detected
print("\n ==========================\n\n")
print("A \"shutdown\" command event was received!\n")
gpg.stop()
exit()

When I run the object_avoidance.py code above within VS Code, it fails with:

pi@Charlene:~/Project_Files/object_avoidance $ /usr/bin/python /home/pi/Project_Files/object_avoidance/Object_Avoidence.py
Traceback (most recent call last):
  File "/home/pi/Project_Files/object_avoidance/Object_Avoidence.py", line 22, in <module>
    keyboard_trigger = Event()
NameError: name 'Event' is not defined
pi@Charlene:~/Project_Files/object_avoidance $

The example of the code that works is quite large, (it's a web-based FPV remote-controlled robot), I've posted it on MediaFire.


Solution

  • The error is due to the Event object not being defined in your code. The Event object comes from the threading module in Python, but you haven't imported it in your Object_Avoidence.py script.

    Just import it at the top.

    from threading import Event