至少我认为那是怎么回事......
我通过串行连接运行两台电机。电机R的控制值范围为1 - 127,电机L的范围为128至255.
我正在使用tkinter来捕捉箭头键按下,然后我将其解释为馈送到电机,这工作正常,除了我想保存当前状态或电机所以我可以知道我是否需要更换电机下一个按键。
在添加多线程之前,它一直有效。
这是试图保存状态的代码:
def save_cur_state(save_state):
print'save_state'
print save_state
print'okay'
if (save_state > 0 and save_state < 128):
last_goodR(save_state)
elif (save_state < 256 and save_state > 127):
last_goodL(save_state)
else:
print'wtf?'
def last_goodR(n):
global cur_stateR_save
cur_stateR_save = n
print 'RRRRRR'
print cur_stateR
def last_goodL(n):
global cur_stateL_save
cur_stateL_save = n
print'LLLL'
print cur_stateL
def get_cur_state():
global cur_stateR_save
global cur_stateL_save
print 'accessing saves'
print cur_stateR_save
print cur_stateL_save
cur_stateR = cur_stateR_save
cur_stateL = cur_stateL_save
return(cur_stateL, cur_stateR)
一切似乎都运行良好,我的版画都给了他们应该做的。 但是,当我再次按下该键时,“已保存”的值都默认为零,我不知道为什么。我已经尝试了十亿种不同的方法来解决它,但我无法让这些值得坚持下去。有谁知道为什么会出现这种情况或我应该如何解决它? (我的整个代码如下,如果你想看到它) 谢谢!!
import rospy
from std_msgs.msg import Int64
from Tkinter import *
import time
from serial import Serial
from multiprocessing import Process
#Defines
M1B = 1
M1S = 64
M1F = 127
M2B = 128
M2S = 192
M2F = 255
S = 0
F = 1
B = 2
L = 3
R = 4
#serialPort = Serial('/dev/ttyAMA0', 9600, timeout = 2)
cur_stateR = M1S
cur_stateL = M2S
next_stateR = M1S
next_state = M2S
main = Tk()
def kp(event):
if event.keysym == 'Up' :
direction_set(F)
elif event.keysym =='Down' :
direction_set(B)
elif event.keysym =='Left' :
direction_set(L)
elif event.keysym =='Right' :
direction_set(R)
else :
print'fooo'
try:
print'try'
cur_stateR
cur_stateL
except NameError:
print'except'
cur_stateR = 0
cur_stateL = 0
last_goodR(0)
last_goodL(0)
def direction_set(direction):
if direction == F:
next_stateR = M1F
next_stateL = M2F
elif direction == B:
next_stateR = M1B
next_stateL = M2B
elif direction == R:
next_stateR = M1B
next_stateL = M2F
elif direction == L:
next_stateR = M1F
next_stateL = M2B
elif direction == S:
next_stateR = M1S
next_stateL = M2S
else:
next_stateR = M1S
next_stateL = M2S
update(next_stateR, next_stateL)
def update(next_stateR, next_stateL):
if (cur_stateR != next_stateR):
p1 = Process(target = motor1, args = (next_stateR,))
p1.start()
if (cur_stateL != next_stateL):
p2 = Process(target = motor2, args = (next_stateL,))
p2.start()
def motor1(next_stateR):
#change the R motor
print'start motor1'
cur_stateR, cur_stateL = get_cur_state()
if (cur_stateR != next_stateR):
#first set to 64
cur_stateR = M1S
refresh(cur_stateR)
time.sleep(1)
# then itterate to the desired stat
if next_stateR == M1F:
for x in range (M1S, M1F+1):
cur_stateR = x
time.sleep(.01)
refresh(cur_stateR)
elif next_stateR == M1B:
for x in range (M1S, M1B-1, -1):
cur_stateR = x
time.sleep(.01)
refresh(cur_stateR)
save_cur_state(cur_stateR)
print 'end motor1'
def motor2 (next_stateL):
#change the L motor
print 'start motor2'
cur_stateR, cur_stateL = get_cur_state()
if (cur_stateL != next_stateL):
#first set to 64
cur_stateL = M2S
refresh(cur_stateL)
time.sleep(1)
# then itterate to the desired stat
if next_stateL == M2F:
for x in range (M2S, M2F+1):
cur_stateL = x
time.sleep(.01)
refresh(cur_stateL)
elif next_stateL == M2B:
for x in range (M2S, M2B-1, -1):
cur_stateL = x
time.sleep(.01)
refresh(cur_stateL)
#print 'to save:'
#print cur_stateR
#print cur_stateL
save_cur_state(cur_stateL)
def refresh(update_state):
#serialPort.write(chr(update_state))
print update_state
def save_cur_state(save_state):
print'save_state'
print save_state
print'okay'
if (save_state > 0 and save_state < 128):
last_goodR(save_state)
elif (save_state < 256 and save_state > 127):
last_goodL(save_state)
else:
print'wtf?'
''' try:
print'try'
cur_stateR
cur_stateL
except NameError:
print'except'
cur_stateR = 0
cur_stateL = 0
last_goodR(0)
last_goodL(0)
else:'''
def last_goodR(n):
global cur_stateR_save
cur_stateR_save = n
print 'RRRRRR'
print cur_stateR
def last_goodL(n):
global cur_stateL_save
cur_stateL_save = n
print'LLLL'
print cur_stateL
def get_cur_state():
global cur_stateR_save
global cur_stateL_save
print 'saves acess'
print cur_stateR_save
print cur_stateL_save
cur_stateR = cur_stateR_save
cur_stateL = cur_stateL_save
return(cur_stateL, cur_stateR)
main.bind_all('<KeyPress>', kp)
main.mainloop()
serialPort.close()
答案 0 :(得分:0)
首先,在尝试使用&#34;线程&#34;做之前,您应该知道tkinter
不是线程安全的;除了创建它们的线程之外,不应该从任何东西访问GUI元素,任何跨线程的使用最多都是不可靠的,并且在其余时间保证是错误的。
其次,您实际上并未参与线程化。您正在使用生成新进程的multiprocessing
,并且这些进程不会与生成它们的进程共享内存(包括全局变量等内容),除非在非常有限的情况下(例如multiprocessing.Array
)。在类UNIX系统上,他们使用fork
,并且一旦Process
开始运行,它就具有原始进程具有的写时复制视图;它可以从fork
的那一刻开始读取相同的数据,但是如果它改变它,它只会更改自己的副本,而不是父进程的副本。 set_cur_state
中的motor1
调用是设置子进程的值副本,但原始进程的副本未经修改。
如果您想使用threading
(使用线程,而不是进程)进行工作,则可以构建this simple example of how to do so。
如果您正在使用multiprocessing
,则可以使用multiprocessing.Queue
采取类似的方法。或者,您可以使用全局multiprocessing.Pool
,而不是启动新的Process
,当您需要调度工作时,您可以在池上调用apply_async
,将功能更改为接受状态作为参数并返回新状态(而不是在内部读取和写入全局变量),并向callback
提供将使用返回值调用的apply_async
函数。注意:据我所知,callback
将使用与工作者通信的线程调用,而不是主线程,因此您仍需要使用示例代码中的技巧将数据传递回所拥有的小部件由主线。