Python Tkinter canvas 绘制串行数据流(数学问题)
Python Tkinter canvas plotting stream of serial data (Math problems)
我正在尝试可视化来自来回旋转 180 度的声纳传感器的数据。
读取传感器数据并使用正则表达式变量处理后 "dist" 包含一个表示距离的浮点数(以厘米为单位)。
变量 "angl" 包含一个介于 0 和 180 之间的整数,表示旋转状态。
到目前为止一切顺利,但我不太清楚如何使用 Tkinter 在 canvas 上表示它。我一直在尝试各种各样的事情,但我已经为这个线程清理了一些代码。
目标是以 canvas 上的点 (1000, 1000) 为中心,将绿色圆圈移动到相应缩放的 (x, y) 坐标。
这是终端的示例读数
角度:174
距离:208.11
X:-72.99856014995218
Y:-194.88710146142
角度:175
距离:161.67
X: 96.75694368800949
Y:-129.51943000243384
角度:176
距离:100.88
X: 100.62718668260311
Y: 7.13748557578522
角度:177
距离:43.61
X: 20.907170903220738
Y: 38.27169064496002
import serial
import re
import math
import tkinter
import time
w_width = 2000
w_height = 1000
def create_animation_window():
window = tkinter.Tk()
window.title("WALL-E SONAR")
window.geometry(f'{w_width}x{w_height}')
return window
def create_animation_canvas(window):
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
return canvas
ser = serial.Serial('/dev/ttyACM0', 9600)
strPort = '/dev/ttyACM0'
def animate_sonar(window, canvas):
intercept = canvas.create_oval(0,0,20,20, fill="green")
while True:
rawData = ser.readline() # rawData input example: b'D:140.98A:57\r\n
decodedData = rawData.decode("utf-8")
line = re.search(r'D:(.*)A:(.*)\r\n', decodedData)
if line:
dist = float(line.group(1))
angl = int(line.group(2))
print(f"ANGLE: {angl}")
print(f"DISTANCE: {dist}")
x = dist * math.cos(angl)
y = dist * math.sin(angl)
print(f"X: {x}")
print(f"Y: {y}")
canvas.moveto(intercept, x,y)
window.update()
animation_window = create_animation_window()
animation_canvas = create_animation_canvas(animation_window)
animate_sonar(animation_window, animation_canvas)
我看到的东西很少:
- 你在 sin 和 cos 中使用的角度应该以弧度为单位
- 您必须使用相对于您的 canvas
的位置
这是我会做的:
import math
import tkinter
import time
window = tkinter.Tk()
window.title("WALL-E SONAR")
window.geometry(f'2000x1000')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
def animate_sonar(window, canvas):
dist = 200
for angl in range(180, 360):
rad = angl * math.pi / 180
x = dist * math.cos(rad) + 300
y = dist * math.sin(rad) + 300
canvas.delete("all")
canvas.create_oval(x-10, y-10, x+10, y+10, fill="green")
canvas.create_line(300, 300, x, y, fill="red")
window.update()
time.sleep(0.05)
animate_sonar(window, canvas)
window.mainloop()
如果你 运行 你应该看到类似的东西:
我的代码中的 300 只是为了放置一些东西,但是您必须调整 window 和 canvas 的尺寸才能将其正确放置在您想要的位置。
rad = angl * math.pi / 180
x = dist * math.cos(rad) + 300
y = dist * math.sin(rad) + 300
从非常简单的事情开始,模拟数据,这将使其他人更容易重现您的代码,然后合并您的传感器。当我第一次读到这个问题时,我差点关闭页面,我的第一个想法是没有那个传感器我无法重现这个...
我也用过 canvas.delete("all")
你的 canvas.moveto
给我错误,但如果它对你完美,请按照与我的示例类似的方式使用它。
希望您走上正确的道路...
我正在尝试可视化来自来回旋转 180 度的声纳传感器的数据。
读取传感器数据并使用正则表达式变量处理后 "dist" 包含一个表示距离的浮点数(以厘米为单位)。 变量 "angl" 包含一个介于 0 和 180 之间的整数,表示旋转状态。
到目前为止一切顺利,但我不太清楚如何使用 Tkinter 在 canvas 上表示它。我一直在尝试各种各样的事情,但我已经为这个线程清理了一些代码。
目标是以 canvas 上的点 (1000, 1000) 为中心,将绿色圆圈移动到相应缩放的 (x, y) 坐标。
这是终端的示例读数
角度:174
距离:208.11
X:-72.99856014995218
Y:-194.88710146142
角度:175
距离:161.67
X: 96.75694368800949
Y:-129.51943000243384
角度:176
距离:100.88
X: 100.62718668260311
Y: 7.13748557578522
角度:177
距离:43.61
X: 20.907170903220738
Y: 38.27169064496002
import serial
import re
import math
import tkinter
import time
w_width = 2000
w_height = 1000
def create_animation_window():
window = tkinter.Tk()
window.title("WALL-E SONAR")
window.geometry(f'{w_width}x{w_height}')
return window
def create_animation_canvas(window):
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
return canvas
ser = serial.Serial('/dev/ttyACM0', 9600)
strPort = '/dev/ttyACM0'
def animate_sonar(window, canvas):
intercept = canvas.create_oval(0,0,20,20, fill="green")
while True:
rawData = ser.readline() # rawData input example: b'D:140.98A:57\r\n
decodedData = rawData.decode("utf-8")
line = re.search(r'D:(.*)A:(.*)\r\n', decodedData)
if line:
dist = float(line.group(1))
angl = int(line.group(2))
print(f"ANGLE: {angl}")
print(f"DISTANCE: {dist}")
x = dist * math.cos(angl)
y = dist * math.sin(angl)
print(f"X: {x}")
print(f"Y: {y}")
canvas.moveto(intercept, x,y)
window.update()
animation_window = create_animation_window()
animation_canvas = create_animation_canvas(animation_window)
animate_sonar(animation_window, animation_canvas)
我看到的东西很少:
- 你在 sin 和 cos 中使用的角度应该以弧度为单位
- 您必须使用相对于您的 canvas 的位置
这是我会做的:
import math
import tkinter
import time
window = tkinter.Tk()
window.title("WALL-E SONAR")
window.geometry(f'2000x1000')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
def animate_sonar(window, canvas):
dist = 200
for angl in range(180, 360):
rad = angl * math.pi / 180
x = dist * math.cos(rad) + 300
y = dist * math.sin(rad) + 300
canvas.delete("all")
canvas.create_oval(x-10, y-10, x+10, y+10, fill="green")
canvas.create_line(300, 300, x, y, fill="red")
window.update()
time.sleep(0.05)
animate_sonar(window, canvas)
window.mainloop()
如果你 运行 你应该看到类似的东西:
我的代码中的 300 只是为了放置一些东西,但是您必须调整 window 和 canvas 的尺寸才能将其正确放置在您想要的位置。
rad = angl * math.pi / 180
x = dist * math.cos(rad) + 300
y = dist * math.sin(rad) + 300
从非常简单的事情开始,模拟数据,这将使其他人更容易重现您的代码,然后合并您的传感器。当我第一次读到这个问题时,我差点关闭页面,我的第一个想法是没有那个传感器我无法重现这个...
我也用过 canvas.delete("all")
你的 canvas.moveto
给我错误,但如果它对你完美,请按照与我的示例类似的方式使用它。
希望您走上正确的道路...