UltraBorg PBR BattBorg and pygame robot. Help request for Python code.
Forums:
Hello PiBorg community,
Firstly I'd like to thank everyone at PiBorg for creating such brilliant boards.
The PBR gives plenty of power to control motors and the BattBorg does an excellent job of powering the Pi from batteries. The UltraBorg is a great bit of kit, offering control over servos and distance sensors. I love them all and have brought them together to create a robot with an onboard pan/tilt camera.
However, I am having some trouble with some Python code that I have cobbled together. I am sure this is a classic case of "operator error" and hopefully, can be easily resolved by someone with more knowledge than myself.
The code is designed to take inputs from a keyboard (wireless) and either move motors controlled by the PBR forwards, backwards, left and right; or move two servos controlled by the UltraBorg up, down, left and right.
The motors work perfectly with the code, but whenever I press a key to operate the servos I receive the following error:-
Traceback (most recent call last): File "/home/pi/picoborgrev/1.2-servo_motorcontrol_PBR_pygame .py", line 118, in servo_up() File "/home/pi/picoborgrev/1.2-servo_motorcontrol_PBR_pygame .py", line 47, in servo_up servo2 += rateServo2 UnboundLocalError: local variable 'servo2' referenced before assignment
I have moved bits of code around trying to resolve the issue, but to no avail.
I have tried to comment the code methodically to show what I am trying to achieve with each section of the program. Hopefully this will help diagnose the source of the problem.
Thank you in advance for your time and any assistance you are able to offer.
Kind regards,
TankMan
PS The code is as follows:-
#!/usr/bin/env python import time import PicoBorgRev import pygame import os import UltraBorg # Settings servoMin = -1.0 # Smallest servo position to use servoMax = +1.0 # Largest servo position to use startupDelay = 0.5 # Delay before making the initial move stepDelay = 0.1 # Delay between steps rateStart = 0.05 # Step distance for all servos during initial move rateServo1 = 0.01 # Step distance for servo #1 rateServo2 = 0.01 # Step distance for servo #2 # Start the UltraBorg UB = UltraBorg.UltraBorg() # Create a new UltraBorg object UB.Init() # Set the board up (checks the board is connected) # Start the PicoBorg Reverse PBR = PicoBorgRev.PicoBorgRev() PBR.Init() PBR.ResetEpo() # Start pygame & define pygame screen size pygame.init() screen = pygame.display.set_mode ((480,480)) print 'Move to central' # Initial settings servo1 = 0.0 servo2 = 0.0 # Set our initial servo positions UB.SetServoPosition1(servo1) UB.SetServoPosition2(servo2) # Wait a while to be sure the servos have caught up time.sleep(startupDelay) # Define servo variables def servo_left(): servo1 += rateServo1 def servo_right(): servo1 -= rateServo1 def servo_up(): servo2 += rateServo2 def servo_down(): servo2 -= rateServo2 # Check if any servos exceed limits and constrain to limit if servo1 > servoMax: servo1 = servoMax if servo1 < servoMax: servo1 = servoMax if servo2 > servoMax: servo2 = servoMax if servo2 < servoMin: servo2 = servoMin # Set our new servo positions UB.SetServoPosition1(servo1) UB.SetServoPosition2(servo2) # Define motor variables def forwards(): PBR.SetMotor1(+0.8) PBR.SetMotor2(+0.7) def back(): PBR.SetMotor1(-0.8) PBR.SetMotor2(-0.7) def left(): PBR.SetMotor1(-0.6) PBR.SetMotor2(+0.6) def right(): PBR.SetMotor1(+0.6) PBR.SetMotor2(-0.6) def stop(): PBR.MotorsOff() def shutdown(): os.system("sudo shutdown -P now") while True: pygame.display.flip() keystate=pygame.key.get_pressed() if keystate[pygame.K_DOWN]: print 'backwards' back() elif keystate[pygame.K_UP]: print 'forwards' forwards() elif keystate[pygame.K_RIGHT]: print 'right' right() elif keystate[pygame.K_LEFT]: print 'left' left() elif keystate[pygame.K_a]: print 'servo left' servo_left() elif keystate[pygame.K_d]: print 'servo right' servo_right() elif keystate[pygame.K_w]: print 'servo up' servo_up() elif keystate[pygame.K_x]: print 'servo down' servo_down() elif keystate[pygame.K_SPACE]: print 'shutdown' shutdown() else: stop() for event in pygame.event.get(): if event.type == pygame.QUIT: stop() exit(0) time.sleep(0.01)
piborg
Mon, 04/11/2016 - 11:29
Permalink
Global vs local values
I think your problem is due to how Python uses variables.
Put simply if you are trying to read a value then Python will use anything it can find.
If you are trying to change a value it expects it to exist locally.
The simplest way to fix this would be to make the
servo1
andservo2
variables global.First change the initial settings to be global:
Then any function which needs them should also make them global, for example:
now these functions will change the global version instead.
TankMan
Wed, 04/20/2016 - 20:31
Permalink
IT LIVES! Thank you very much.
Hi piborg,
IT LIVES!
Thank you very much for your superbly swift and very helpful reply.
It has been a pretty busy week, so please accept my apology for not replying sooner.
I have managed to implement your code correctly and the pan/tilt mechanism is finally working.
I will tweak the code that limits the up/down and left/right limits and add a key-press that centres the mechanism, but, right now it works and I'm smiling from ear to ear.
I may be re-inventing the wheel a bit with this code, as I know that you have a web GUI. I will find time to explore it.
This code runs without wifi, controlled by a bluetooth keyboard and there are merits to that.
It has been a superb learning experience and your help has been the icing on the cake.
I wish you all the very best of fortune.
Kind regards,
TankMan