Python 机器人控制器代码:加载时出错

Python 机器人控制器代码:加载时出错,python,multithreading,serial-port,raspberry-pi,Python,Multithreading,Serial Port,Raspberry Pi,我用串口写了一个简单的串口控制器——实际上,它更像是Frankstein代码,是其他人写的,我拼凑起来的。请随意嘲笑我的无能,但任何指导都将不胜感激。它在我的Linux运行回溯(Python2.6)上运行良好,但当我尝试在Raspberry Pi(Python2.7)上运行它时,会出现以下错误: Traceback (most recent call last):Exception in thread Thread-2: Traceback (most recent call last):

我用串口写了一个简单的串口控制器——实际上,它更像是Frankstein代码,是其他人写的,我拼凑起来的。请随意嘲笑我的无能,但任何指导都将不胜感激。它在我的Linux运行回溯(Python2.6)上运行良好,但当我尝试在Raspberry Pi(Python2.7)上运行它时,会出现以下错误:

Traceback (most recent call last):Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 147, in rx
    self.ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1, bytesize=8, stopbits=1)
  File "/usr/local/lib/python2.7/dist-packages/serial/serialutil.py", line 260, in __init__
    self.open()
  File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 276, in open
    raise SerialException("could not open port %s: %s" % (self._port, msg))
SerialException: could not open port /dev/ttyUSB0: [Errno 2] No such file or directory: '/dev/ttyUSB0'

File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 185, in <module>
    client = ThreadedClient(root)
  File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 113, in __init__
    self.periodicCall()
  File "/home/pi/Zombie Python 1.2 (Modified for Pi) (from Adapt 1.7).py", line 119, in periodicCall
    self.gui.processIncoming()
AttributeError: GuiPart instance has no attribute 'processIncoming'
Traceback(最近一次调用last):线程2中的异常:
回溯(最近一次呼叫最后一次):
文件“/usr/lib/python2.7/threading.py”,第551行,在引导程序内部
self.run()
文件“/usr/lib/python2.7/threading.py”,第504行,正在运行
自我目标(*自我参数,**自我参数)
rx中第147行的文件“/home/pi/Zombie Python 1.2(针对pi进行了修改)(来自Adapt 1.7.py)”
self.ser=serial.serial('/dev/ttyUSB0',9600,超时=1,字节大小=8,停止位=1)
文件“/usr/local/lib/python2.7/dist packages/serial/serialutil.py”,第260行,在__
self.open()
文件“/usr/local/lib/python2.7/dist packages/serial/serialposix.py”,第276行,打开
raise SerialException(“无法打开端口%s:%s”%(self.\u port,msg))
SerialException:无法打开端口/dev/ttyUSB0:[Errno 2]没有这样的文件或目录:'/dev/ttyUSB0'
文件“/home/pi/Zombie Python 1.2(针对pi进行了修改)(来自Adapt 1.7.py)”,第185行,在
client=ThreadedClient(root)
文件“/home/pi/Zombie Python 1.2(针对pi进行了修改)(来自Adapt 1.7.py)”,第113行,在__
self.periodicCall()
文件“/home/pi/Zombie Python 1.2(针对pi进行了修改)(来自Adapt 1.7.py)”,第119行,在periodicCall中
self.gui.processIncoming()
AttributeError:GuiPart实例没有属性“processIncoming”
我的代码是:

import Tkinter
import time
import threading
import random
import Queue
import serial
import readline
#import xbee
import sys

x=""

class GuiPart:
    def __init__(self, master, queue, endApplication):
       self.sonar = Tkinter.StringVar() # Feeds sonar sensor data to label       
       self.lm = Tkinter.StringVar()    # Feeds left motor speed to label    
       self.rm = Tkinter.StringVar()    # Feeds right motor speed to label      


       self.queue = queue
       # Set up the GUI
       frame1 = Tkinter.Frame(master, bd=200) #Setup frame.
       frame1.bind("<Key>", key) # Allow frame to handle keypresses.
       frame1.focus_set() #Set focus of frame so that keypresses activate event.
       frame1.pack() #Show it.

       #Button
       console = Tkinter.Button(frame1, text='Close', command=endApplication)
       console.pack()

       # Add more GUI stuff here
       self.lm.set(0) # Initializes left motor label
       self.rm.set(0) # Initializes right motor label
       self.sonar.set(0) # Initializes sonar label 

       #Sonar label
       sonarLbl = Tkinter.Label(frame1, textvariable=self.sonar)
       sonarLbl.pack()

       #Right motor label
       rmLbl = Tkinter.Label(frame1, text="Left Motor Speed: ", textvariable=self.rm)
       rmLbl.pack()

       #Left motor label
       lmLbl = Tkinter.Label(frame1, textvariable=self.lm)
       lmLbl.pack()


def key(self, event):
       #print "pressed", repr(event.char)  
       #self.sonar = repr(event.char) <------ This should be the line to handle keypresses
       global x    
       x = repr(event.char)

def processIncoming(self):
       """
       Handle all the messages currently in the queue (if any).
       """
       while self.queue.qsize():
           try:
               msg = self.queue.get(0)
               # Check contents of message and do what it says
               # As a test, we simply print it

           # Below is where I will parse the "msg" variable, splitting 
           # it (msg.rsplit) to pull out sensor data and update labels.

               lm, rm, sonar, mknt = msg.rsplit(",")
               lm = "Left Motor Speed: "+lm
               rm = "Right Motor Speed: "+rm
               sonar = "Sonar: "+sonar+" CMs away"

               self.sonar.set(sonar) # Setting the labels with latest sensor info.
               self.lm.set(lm) # Setting the labels with latest sensor info.
               self.rm.set(rm) # Setting the labels with latest sensor info.

           except Queue.Empty:
                pass

class ThreadedClient:
    """
    Launch the main part of the GUI and the worker thread. periodicCall and
    endApplication could reside in the GUI part, but putting them here
    means that you have all the thread controls in a single place.
    """
    def __init__(self, master):
        """
        Start the GUI and the asynchronous threads. We are in the main
        (original) thread of the application, which will later be used by
        the GUI. We spawn a new thread for the worker.
        """
        self.master = master

        # Create the queue
        self.queue = Queue.Queue()

        # Set up the GUI part
        self.gui = GuiPart(master, self.queue, self.endApplication)

        # Set up the thread to do asynchronous I/O
        # More can be made if necessary
        self.running = 1

        self.thread1 = threading.Thread(target=self.workerThread1)
        self.thread1.start()

        #Start receiving thread.    
        self.rx = threading.Thread(target=self.rx)
        self.rx.start()

        # Start the periodic call in the GUI to check if the queue contains
        # anything
        self.periodicCall()

    def periodicCall(self):
        """
        Check every 100 ms if there is something new in the queue.
        """
        self.gui.processIncoming()
        if not self.running:
            # This is the brutal stop of the system. You may want to do
            # some cleanup before actually shutting it down.
            import sys
            sys.exit(1)
        self.master.after(100, self.periodicCall)

    def workerThread1(self):
        """
        This is where we handle the asynchronous I/O. For example, it may be
        a 'select()'.
        One important thing to remember is that the thread has to yield
        control.
        """
        while self.running:
            # To simulate asynchronous I/O, we create a random number at
            # random intervals. Replace the following 2 lines with the real
            # thing.
            time.sleep(rand.random() * 0.3)
            msg = rand.random()

        #self.queue.put(msg)


    # Continuously read and print packets
    def rx(self):
        global x
        self.ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1, bytesize=8, stopbits=1)
        self.ser.flush()
        while(1):
            response = str(self.ser.readline())

            # Send movement codes.      
            if x == "'a'" or x == "'A'": # or "'A'": # Turn left.
             self.ser.write('4')
            elif x == "'w'" or x == "'W'": #Go forward.
             self.ser.write("3")
            elif x == "'d'" or x == "'D'": #Turn right.
             self.ser.write("2")
            elif x == "'s'" or x == "'S'": #Go back.
             self.ser.write("1")
            elif x == "'x'" or x == "'X'": #Stop.
             self.ser.write("5")
            elif x == "'1'": #Raise speed.
             self.ser.write("7")
            elif x == "'2'": #Lower speed.
             self.ser.write("6")

            x = ""

            if len(response) > 10:
                self.ser.flushInput() #If you don't flush the buffer, then it'll try to read out all 
                                 #the sensor readings, so the reaction time will be extrordinary.
                time.sleep(.1)# This scales back the CPU usage.
                self.queue.put(response)

    def endApplication(self):
        print "Closing"
        self.running = 0
        self.ser.close()    
        sys.exit(1)

rand = random.Random()
root = Tkinter.Tk()

client = ThreadedClient(root)
root.mainloop()
导入Tkinter
导入时间
导入线程
随机输入
导入队列
导入序列号
导入读线
#导入xbee
导入系统
x=“”
类GuiPart:
定义初始化(self、master、queue、endApplication):
self.sonar=Tkinter.StringVar()#将声纳传感器数据提供给标签
self.lm=Tkinter.StringVar()#将左电机转速输入标签
self.rm=Tkinter.StringVar()#为标签提供正确的电机转速
self.queue=队列
#设置GUI
frame1=Tkinter.Frame(主控,bd=200)#设置帧。
框架1.绑定(“,键)#允许框架处理按键。
frame1.focus_set()#设置帧的焦点,以便按键激活事件。
frame1.pack()#显示它。
#钮扣
console=Tkinter.Button(frame1,text='Close',command=endApplication)
console.pack()
#在这里添加更多GUI内容
self.lm.set(0)#初始化左电机标签
self.rm.set(0)#初始化右电机标签
self.sonar.set(0)#初始化声纳标签
#声纳标签
sonarLbl=Tkinter.Label(frame1,textvariable=self.sonar)
sonarLbl.pack()
#右马达标签
rmLbl=Tkinter.Label(frame1,text=“左电机转速:”,textvariable=self.rm)
rmLbl.pack()
#左马达标签
lmLbl=Tkinter.Label(frame1,textvariable=self.lm)
lmLbl.pack()
def键(自身、事件):
#打印“按下”,报告(event.char)
#self.sonar=repr(event.char)10:
self.ser.flushInput()#如果不刷新缓冲区,它将尝试读取所有数据
#传感器读数,因此反应时间将异常。
time.sleep(.1)#这会降低CPU使用率。
self.queue.put(响应)
def端应用程序(自身):
打印“结束”
self.running=0
self.ser.close()
系统出口(1)
rand=random.random()
root=Tkinter.Tk()
client=ThreadedClient(root)
root.mainloop()

您的
self.gui
GuiPart
GuiPart
没有
processIncoming

您的
self.gui
GuiPart
<代码>GuiPart在代码段中的行上方没有显示
processIncoming

def key(self, event):

不再被四个空格缩进,因为它们可能应该成为类的方法
GuiPart

来自其他语言的Python新手经常忽略缩进是Python编程语言语法中非常重要的一部分这一细节。因此,避免选项卡和空间混合也是非常重要的。 (尤其是从不同来源复制代码段时,否则 (学习和尝试新事物的绝佳机会)

另一件事是:在Python中,您还可以定义模块级全局函数。 执行此操作的语法实际上与用于在类中定义方法的语法相同(缩进级别除外)

因此,在您的示例代码片段中,前面的方法
key()
processIncoming()
已经成为模块全局函数定义,而不是简单地通过错误的缩进来定义方法

方法是类对象的属性。这两种方法被移动了 从类名空间一级到模块名空间。 因此出现以下错误消息:

AttributeError: GuiPart instance has no attribute 'processIncoming'

在代码段中,显示在行上方

def key(self, event):

不再被四个空格缩进,因为它们可能应该成为类的方法
GuiPart

来自其他语言的Python新手经常忽略缩进是Python编程语言语法中非常重要的一部分这一细节。因此,避免选项卡和空间混合也是非常重要的。 (尤其是从不同来源复制代码段时,否则 (学习和尝试新事物的绝佳机会)

另一件事是:在Python中,您还可以定义模块级全局函数。 执行此操作的语法实际上与用于在类中定义方法的语法相同(除了