我对 python 编程相当陌生,我正在努力使用 Vispy 库。
基本上,我有一个 Raspberry pi 连接到 2 个 Arduinos 加速度计传感器。覆盆子通过 UDP 将两个传感器的 X、Y 和 Z 值发送到我的计算机。然后我的电脑必须显示 9 个图表:6 个表示两个传感器的 x、y 和 z 的演变,3 个表示它们之间的差异(X1-X2、Y1-Y2 和 Z1-Z2),最后,它必须是真实的-时间。
最后一点我想使用 Vispy 库。阅读文档后,我想出了以下代码:
#!/usr/bin/env python3
import numpy as np
from vispy import app
from vispy import gloo
import socket
from itertools import count
# init x, y arrays
x1_vals = []
time_vals = []
#UDP connection from Raspberry pi
UDP_IP = ""
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
# Initialize the index and set it to 1
index = count()
next(index)
# Initialize the Canvas c
c = app.Canvas(keys='interactive')
vertex = """
attribute vec2 a_position;
void main (void)
{
gl_Position = vec4(a_position, 0.0, 1.0);
}
"""
fragment = """
void main()
{
gl_FragColor = vec4(0.0, 0.0, 15.0, 10.0);
}
"""
program = gloo.Program(vertex, fragment)
@c.connect
def on_resize(event):
gloo.set_viewport(0, 0, *event.size)
@c.connect
def on_draw(event):
gloo.clear((1,1,1,1))
program.draw('line_strip')
def on_timer(event):
# next index
cpt = next(index)
# Get data from UDP
recv, addr = sock.recvfrom(1024)
data = recv.decode('UTF-8').split(';')
# We want to display only 100 samples so the graph still readable.
# So we delete the first value of the x array if there are more than 100 values
if (cpt > 100):
del x1_vals[0]
time_vals = np.linspace(-1.0, +1.0, 100)
else:
time_vals = np.linspace(-1.0, +1.0, cpt)
# The values must be bound between -1.0 and 1.0
tmp = float(data[0])*0.5
if (tmp >= 1):
tmp = float(0.99)
elif (tmp <= -1):
tmp = float(-0.99)
x1_vals.append(tmp)
# Then we concatenate the arrays of x and y
program['a_position'] = np.c_[time_vals, x1_vals].astype(np.float32)
c.update()
c.timer = app.Timer('auto', connect=on_timer, start=True)
c.show()
app.run()
因此,正如评论所描述的,它首先初始化 UDP 连接和画布,然后对于收到的每个值,它都会用新添加的值更新画布。如果值的数量超过 100,则删除数组的第一个值以保持恒定数量的样本。
当我只想显示 X1 加速度计传感器的演变时,它工作得很好。所以现在我从 Vispy 文档中选择了代码,该文档演示了如何显示多个图形,但是对于我的关卡来说,代码有点太复杂了。
基本上,在我的代码中,我收到了data
数组中的所有传感器值。我选择第一个值 [0] (X1),但完整的数据如下所示:[x1, y1, z1, dx, dy, dz, x2, y2, z2]
其中 dx = x1 - x2,dy = y1 - y2 和 dz = z1 - z2。(差异必须直接在树莓上计算)。
因此,我尝试修改文档中的代码,如下所示:
# Number of cols and rows in the table.
nrows = 3
ncols = 3
# Number of signals.
m = nrows*ncols
# Number of samples per signal.
n = 100
因为我想要 9 个图,每个图只有 100 个样本。
我忽略了索引、颜色并删除了振幅,因为我不需要它。基本上,我几乎保留了整个设置部分的原始代码,然后我用我的替换了def on_timer
。
现在我正在尝试a_position
用我自己的数据从 GLSL 提供数组。但我不确定如何准备数据以使其与此代码正常工作。我正在努力理解这些行的作用:
# GLSL C code
VERT_SHADER = """
// Compute the x coordinate from the time index.
float x = -1 + 2*a_index.z / (u_n-1);
vec2 position = vec2(x - (1 - 1 / u_scale.x), a_position);
// Find the affine transformation for the subplots.
vec2 a = vec2(1./ncols, 1./nrows)*.9;
vec2 b = vec2(-1 + 2*(a_index.x+.5) / ncols,
-1 + 2*(a_index.y+.5) / nrows);
// Apply the static subplot transformation + scaling.
gl_Position = vec4(a*u_scale*position+b, 0.0, 1.0);
"""
# Python code
def __init__(self):
self.program['a_position'] = y.reshape(-1, 1)
def on_timer(self, event):
k = 10
y[:, :-k] = y[:, k:]
y[:, -k:] = amplitudes * np.random.randn(m, k)
self.program['a_position'].set_data(y.ravel().astype(np.float32))
我删除了我认为我理解的周围代码。
请注意,即使我从 python 开始,当我在代码中使用裸对象时,我也知道他们正在使用 Canvas 的类定义。我了解self
和其他人的使用。
如何使 realtime_signals 文档中的代码适应我的情况?