Как многопоточность в Python - проект робота - PullRequest
0 голосов
/ 10 июня 2019

Я делаю проект робота, где у меня есть 4 сервопривода (2 ведущих и 2 рулевых) и 2 отдельных бесщеточных мотора.Мое намерение состоит в том, чтобы иметь возможность вести и управлять роботом, в то время как 2 BLDC вращаются с заданной скоростью.Кроме того, я использую библиотеку XboxController, чтобы использовать контроллер для управления и руления.Я думал о многопоточности, и это код, который я придумал.Однако, как только запускается второй поток (init2Thread), он зацикливается навсегда, и я не могу управлять роботом, ни BLDC работают ... Есть ли способ запустить BLDC в фоновом режиме и управлять / управлять роботом?

import math
import os
import pigpio
import sys
import time
import XboxController2
from threading import Thread

pi = pigpio.pi()

#servo pin values setup
ESCf = 17
ESCr = 22
RDservoPin = 23
LDservoPin = 4
RSservoPin = 19
LSservoPin = 21

pi.set_servo_pulsewidth(ESCf, 0)
pi.set_servo_pulsewidth(ESCr, 0)

class gamepadControl:

    def __init__(self):

        #setup controller values
    self.xValue = 0
    self.yValue = 0
    self.xrValue = 0
    self.yrValue = 0

    #create xbox controller class
    self.xboxCont = XboxController2.XboxController(deadzone = 30, scale = 100, invertYAxis = False)

    #setup call backs
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.LTHUMBX, self.leftThumbX)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.LTHUMBY, self.leftThumbY)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.RTHUMBY, self.rightThumbX)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.RTHUMBY, self.rightThumbY)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.XBOX, self.xboxButton)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.START, self.startButton)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.A, self.aButton)
    self.xboxCont.setupControlCallback(self.xboxCont.XboxControls.B, self.bButton)

    #start the controller
    self.xboxCont.start()
    self.running = True

#callback funtions for left thumb stick
def leftThumbX(self, xValue):
    self.xValue = xValue
    self.updateMotors()

def leftThumbY(self, yValue):
    self.yValue = yValue
    self.updateMotors()

#callback funtions for right thumb stick
def rightThumbX(self, xrValue):
    self.xrValue = xrValue
    self.updateMotors()

def rightThumbY(self, yrValue):
    self.yrValue = yrValue
    self.updateMotors()

#callback funcion for xbox button
def xboxButton(self, value):
    global RDservoPin
    global LDservoPin
    global ESCf
    global ESCr

    pi.set_servo_pulsewidth(RDservoPin, 0)
    pi.set_servo_pulsewidth(LDservoPin, 0)

    pi.set_servo_pulsewidth(ESCf, 0)
    pi.set_servo_pulsewidth(ESCr, 0)

    self.stop()

def startButton(value):
    if value == 1:
        print value

#callback function for X button
def aButton(self, value):
    if value == 1:
        print value

#callback function for O button
def bButton(self, value):
    if value == 1:
        print value
#stop
def stop(self):
    self.xboxCont.stop()
    self.running = False
    pi.stop() 

def updateMotors(self):
    #angle calculations
    angle = math.degrees(math.atan2(self.xValue, self.yValue))
    length = math.hypot(self.xValue, self.yValue)

    #servo motors pin setup
    global RDservoPin
    global LDservoPin
    global RSservoPin
    global LSservoPin

    #setting pins to output
    pi.set_mode(RDservoPin, pigpio.OUTPUT)
    pi.set_mode(LDservoPin, pigpio.OUTPUT)
    pi.set_mode(RSservoPin, pigpio.OUTPUT)
    pi.set_mode(LSservoPin, pigpio.OUTPUT)

    #setting motors starting values
    pi.set_servo_pulsewidth(RDservoPin, 0)
    pi.set_servo_pulsewidth(LDservoPin, 0)
    pi.set_servo_pulsewidth(RSservoPin, 1500)
    pi.set_servo_pulsewidth(LSservoPin, 1500)

    #conditions
    if angle == 180 and length >= 50:
        pi.set_servo_pulsewidth(RDservoPin, 600)
        pi.set_servo_pulsewidth(LDservoPin, 1600)

        if self.yrValue < 0:
            pw = ((self.yrValue * 2000) / 284) + 1500
            pi.set_servo_pulsewidth(RSservoPin, pw)
            pi.set_servo_pulsewidth(LSservoPin, pw)

        elif self.yrValue > 0:
            pw = ((self.yrValue * 2000) / 284) + 1500
            pi.set_servo_pulsewidth(RSservoPin, pw)
            pi.set_servo_pulsewidth(LSservoPin, pw)

    elif angle == 0 and length >= 50:
        pi.set_servo_pulsewidth(RDservoPin, 1600)
        pi.set_servo_pulsewidth(LDservoPin, 600)

        if self.yrValue < 0:
            pw = ((self.yrValue * 2000) / 284) + 1500
            pi.set_servo_pulsewidth(RSservoPin, pw)
            pi.set_servo_pulsewidth(LSservoPin, pw)

        elif self.yrValue > 0:
            pw = ((self.yrValue * 2000) / 284) + 1500
            pi.set_servo_pulsewidth(RSservoPin, pw)
            pi.set_servo_pulsewidth(LSservoPin, pw)

    elif self.yrValue < 0:
        pw = ((self.yrValue * 2000) / 284) + 1500
        pi.set_servo_pulsewidth(RSservoPin, pw)
        pi.set_servo_pulsewidth(LSservoPin, pw)

    elif self.yrValue > 0:
        pw = ((self.yrValue * 2000) / 284) + 1500
        pi.set_servo_pulsewidth(RSservoPin, pw)
        pi.set_servo_pulsewidth(LSservoPin, pw)

    elif angle == 0 and length == 0 and self.yrValue == 0: 
        pi.set_servo_pulsewidth(RDservoPin, 0)
        pi.set_servo_pulsewidth(LDservoPin, 0)

        pi.set_servo_pulsewidth(RSservoPin, 1500)
        pi.set_servo_pulsewidth(LSservoPin, 1500)

class runEngines:

def __init__(self):

    #start
    self.running = True

    global ESCf
    global ESCr

    pi.set_servo_pulsewidth(ESCf, 1000)
    pi.set_servo_pulsewidth(ESCr, 1000)
    time.sleep(1)

def run(self):
    global ESCf
    global ESCr

    while True:
        pi.set_servo_pulsewidth(ESCf, 1030)
        pi.set_servo_pulsewidth(ESCr, 1030)

if __name__ == '__main__':
print ("START")
try:
    #create class
    init = gamepadControl()

    updateMotors = init.updateMotors()
    initThread = Thread(target = updateMotors)
    initThread.start()

    init2 = runEngines()
    run = init2.run()
    init2Thread = Thread(target = run)
    init2Thread.start()

#Ctrl C
except KeyboardInterrupt:
    print ("USER CANCELLED")
#Error
except:
    print ("ERROR:"), sys.exc_info()[0]
    raise

finally:
    print 
    print ("STOP")
    #if its still running (probably because an error occured, stop it
    if init.running == True:
        init.stop()
...