1

我正在为我的大学参加比赛的机器人编写代码。我目前正在尝试使用反射传感器构建一些车轮编码器。不久前我意识到我可能需要使用线程来实现这一点,因为机器人需要同时监控左右编码器。下面的代码是我到目前为止所拥有的:

from __future__ import division
import threading
import time
from sr import *
R = Robot()

class Encoder(threading.Thread):
    def __init__(self, motor, pin, div=16):
        self.motor = motor
        self.pin = pin
        self.div = div
        self.count = 0
        threading.Thread.__init__(self)

    def run(self):
        while True: 
            wait_for(R.io[0].input[self.pin].query.d)
            self.count += 1

    def rotations(self, angle, start_speed=50):
        seg = 360/self.div
        startcount = self.count
        current_dist = angle #Distance away from target
        R.motors[self.motor].target = start_speed
        while current_dist > 360:
            newcount = self.count - startcount
            current_dist = angle - newcount*seg
            R.motors[self.motor].target = 50
        while abs(current_dist) > seg/2:  
            newcount = self.count - startcount
            current_dist = angle - newcount*seg
            current_speed = start_speed * current_dist / 360
            if current_speed < 5:
                R.motors[self.motor].target = 5
            else:
                R.motors[self.motor].target = current_speed
        R.motors[self.motor].target = 0

WheelLeft = Encoder(0,0)
WheelLeft.start()
WheelRight = Encoder(1,3)
WheelRight.start()

WheelRight.rotations(720)
WheelLeft.rotations(720)

sr 模块由举办比赛的南安普顿大学提供。它允许我们与机器人的硬件进行交互。

现在,创建的线程似乎允许分别监控两个反射传感器。这段代码:R.io[0].input[self.pin].query.d计算来自反射传感器的值是否发生了变化。“旋转”方法通过不断检查车轮已经转动了多少度,并在到达终点时减慢速度,将车轮转动一定角度。我希望两个轮子在我运行程序时都开始转动,然后在它们经过 2 圈后减速并停止。目前,当我运行程序时,一个轮子开始转动并减速并停止,然后是另一个轮子。在我看来,“旋转”方法没有在线程中运行,就像“运行”方法一样。是不是只有'run'方法下的代码在线程中运行,

如果有帮助,我一直在关注本教程: http: //www.devshed.com/c/a/Python/Basic-Threading-in-Python/1/

另外,我想知道为什么只能用Encoder(0,0).start(). 为什么你不必使用类创建一个对象(例如Thread = Encoder(0,0).start()创建一个新线程?

抱歉,如果我使用的术语不符合标准,因为您可能会说我对线程和一般编程很陌生。

4

3 回答 3

1

Encoder(0,0).start()是对启动线程的方法的调用。反过来,此方法调用您的run实现,它不使用该rotations方法。如果你想这样做,那么你必须在 的 while 循环中调用它run

随着Thread = Encoder(0,0).start()您存储从该调用检索到的值(即无),但要获得它,您需要首先启动新线程。

于 2013-03-21T22:07:40.840 回答
0

run 方法执行的线程。

如果您希望在该线程中发生其他事情,则必须从Encoder.run().

哦,Encoder(0,0).start() 确实创建了一个对象。仅仅因为您没有将该对象绑定到局部变量并不意味着它不存在。如果它不存在,你就不能调用它的start方法。

但是,您必须非常小心它的生命周期,没有局部变量来保持它的生命周期。

于 2013-03-21T22:14:57.477 回答
0

您可以从 SR 的类扩展,Poll以便它可以用于wait_for

import poll

class Encoder(poll.Poll):
    def __init__(self, motor, pin, div=16):
        self.motor = motor
        self.pin = pin
        self.div = div
        self.count = 0
        self.target_reached = False

        # kick off a thread to count the encoder ticks
        self.counter_thread = threading.Thread(target=self._update_count)
        self.counter_thread.start()

    def _update_count(self):
        while True: 
            wait_for(R.io[0].input[self.pin].query.d)
            self.count += 1

    def rotations(self, angle, start_speed=50):
        if not self.target_reached:
            raise Exception("Last motion still in progress!")

        self.target_reached = False

        # kick off a thread to control the speed
        self.angle_thread = threading.Thread(
            target=self._update_speeds,
            args=(angle, start_speed)
        )
        self.angle_thread.start()

    def _update_speeds(self, angle, start_speed):
        # control the motor speed as before
        ...

        # let things know we're done
        self.target_reached = True

    # implement poll methods
    def eval(self):
        return (self.target_reached, None)

然后,您可以这样做:

wheelLeft = Encoder(0,0)
wheelRight = Encoder(1,3)

wheelRight.rotations(720)
wheelLeft.rotations(720)

wait_for(wheelRight & wheelLeft)

请注意,编码器本身不是线程 - 它是“具有”关系,而不是“是”关系

于 2013-12-17T10:19:15.620 回答