2
#!/usr/bin/python

import rospy
import serial
import time
from std_msgs.msg import String

ser = serial.Serial('/dev/ttyUSB0', 9600)
print (ser.name)
time.sleep(2)

#===========================================================
# An o y ine i kateuthynsi kinisis (mikos deksamenis)
# Gia kinisi se eutheia
x_d = 0 # mm
y_d = 2000
thita_d = 0 # moires i rads
#===========================================================

camera = [0, 0, 0]
error = [0, 0, 0]
data = [0, 0, 0]
print(data)
def camera_feedback():
    # dedomena apo camera-RPi-seiriaka apo allon komvo mallon...
    #camera = [x_c, y_c, thita_c]
    #x_c = camera[0]                    #isws mpei kwdikas gia na diavazei apo tin
    camera[0] = 0
    #y_c = camera[1]                    #seiriaki tu RPi (opws to serial_connection())
    camera[1] = camera[1] + 250
    #thita_c = camera[2]    
    camera[2] = 0
    print(camera)

def error_calculation():
    error[0] = x_d - camera[0]
    error[1] = y_d - camera[1]
    error[2] = thita_d - camera[2]
    print(error)

def controller_equations():
    # edw mpenun oi eksiswseis tu michali
    # kapws pernei to error kai alla dedomena kai dinei w, A, thita_mesi gia na stalun ston PIC
    if error != [0, 0, 0]:
        print(error)
        print(data)
        data[0] = 8
        data[1] = 8
        data[2] = 0
    else:
        data = [0, 0, 0]
    print('kokos')
    #data = [w, A, thita_mesi]     #na dw ti format dexete o kwdikas tu PIC

def serial_connection():
    rospy.init_node('serial_connection', anonymous = True)
    rate = rospy.Rate(10) #isws na min xreiazetai

    if not rospy.is_shutdown():

        ##data1 = bytearray(data)
        ##rdata = bytearray()
        ##rdata.extend(data1[0:2])
        ##rdata.extend(data1[2:5])
        ##vect = list(rdata)
        ##print(vect)

        if ser.isOpen():
            print ("Port Open")
            for i in range(1):
                #ser.write(b'5')
                #ser.write(chr(5)) auto stelnei kwdikopoiimenus xaraktires, ox$
                #ser.write(5)
                ser.write(bytes(data) + '\n')
                #print ('Hola!')
                #ser.write("Hola!\n")
                time.sleep(1)
                rate.sleep()

if __name__ == '__main__':
    try:
        while not rospy.is_shutdown():
            camera_feedback()
            error_calculation()
            controller_equations()
            serial_connection()
        ser.close()
    except rospy.ROSInterruptException:
        pass

I run the code above and I get the error: UnboundLocalError: local variable 'data' referenced before assignment

I want to change the value of the global variable data through the function controller_equations(). I did the same with the variable camera in the function camera_feedback() without any error. I searched other posts for an answer but all of them say that is not possible to chance a global variable through a function. Any possible solution or a tip will be appreciated. I am new in Python and I use Ubuntu 16.04 and Python 2.7.

Thanks in advance.

Meanmachine
  • 97
  • 12
  • I too answered quickly it is to do with globals. now I'm curious too. There is an alignment issue in the controller_equations() code block. Am sure you would have got: IndentationError. Hope you are getting UnboundLocalError after fixing this. Is it possible to post the stack trace to confirm line triggering this error ? – user2390183 Nov 06 '18 at 11:46

1 Answers1

2

As already pointed out by duplicate post response, you need to use globals to solve this problem

However, to explain why it worked in camera_feedback but not in controller_equations

You don't need globals statement to access global variables directly in function context !!. However it is not advised to save your life time from debugging problem like this

To resolve a variable, interpreter always looks in local name space for variable (precisely label) reference before searching in global (immediate parent) name space

In camera_feedback, interpreter looks in local name space for variable camera, when it evaluates camera[0] = 0. As it is not found it looks in its immediate parent (i.e module ) namespace

In controller_equations you have created a new environment context within function context by if..else statement. As the variable data is not found in local name space (if..else context, it would be looked in immediate parent i.e function context which also has no reference to data,so it throws UnboundLocalError error

To solve this you need to include data from module name space to function name space by the statement globals data , so that all the nested environment within function can access them (Disclaimer: This is oversimplification of how internals handles scoping)

Hope this helps!

user2390183
  • 975
  • 8
  • 17