通过串行数据使用 Python mplotlib 动画 3D 散点图
Animating 3D scatter plot using Python mplotlib via serial data
我正在尝试使用 Python 中的 mplotlib 制作 3D 散点图的动画。我每次都能绘制数据图表并重新绘制,但这会导致帧速率低于 1 FPS,我需要扩展到 30 FPS 以上。当我 运行 我的代码:
import serial
import numpy
import matplotlib.pyplot as plt #import matplotlib library
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *
import matplotlib.animation
import time
ser = serial.Serial('COM7',9600,timeout=5)
ser.flushInput()
time.sleep(5)
ser.write(bytes(b's1000'))
x=list()
y=list()
z=list()
#plt.ion()
fig = plt.figure(figsize=(16,12))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(x,y,z, c='r',marker='o')
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
def generate():
while True:
try:
ser_bytes = ser.readline()
data = str(ser_bytes[0:len(ser_bytes)-2].decode("utf-8"))
xyz = data.split(", ")
dx = float(xyz[0])
dy = float(xyz[1])
dz = float(xyz[2].replace(";",""))
x.append(dx);
y.append(dy);
z.append(dz);
graph._offset3d(x,y,z, c='r',marker='o')
except:
print("Keyboard Interrupt")
ser.close()
break
return graph,
ani = matplotlib.animation.FuncAnimation(fig, generate(), interval=1, blit=True)
plt.show()
我收到以下错误:
Traceback (most recent call last):
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1026, in _start
self._init_draw()
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1750, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
TypeError: 'tuple' object is not callable
Traceback (most recent call last):
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1308, in _handle_resize
self._init_draw()
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1750, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
TypeError: 'tuple' object is not callable
我从连接到 Arduino 的激光雷达模块接收 x、y、z 坐标,Arduino 通过串行方式将坐标发送到 Python 脚本。
您的代码可能存在的问题是动画函数 (generate
) 不应该 运行 在无限循环中。此外,您应该将对该函数的引用传递给 FuncAnimate
,但您实际上是在调用该函数(即您需要省略 FuncAnimation(..., generate, ...)
中的括号
第二个问题是,当 graph._offset3d
只是一个列表元组时,您将其视为一个函数。您应该为其分配一个新的元组,而不是尝试 调用 函数(我相信这是错误消息所暗示的)。
我简化了您的代码,以下工作正常:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
def update_lines(num):
dx, dy, dz = np.random.random((3,)) * 255 * 2 - 255 # replace this line with code to get data from serial line
text.set_text("{:d}: [{:.0f},{:.0f},{:.0f}]".format(num, dx, dy, dz)) # for debugging
x.append(dx)
y.append(dy)
z.append(dz)
graph._offsets3d = (x, y, z)
return graph,
x = [0]
y = [0]
z = [0]
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(x, y, z, color='orange')
text = fig.text(0, 1, "TEXT", va='top') # for debugging
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
# Creating the Animation object
ani = animation.FuncAnimation(fig, update_lines, frames=200, interval=50, blit=False)
plt.show()
我正在尝试使用 Python 中的 mplotlib 制作 3D 散点图的动画。我每次都能绘制数据图表并重新绘制,但这会导致帧速率低于 1 FPS,我需要扩展到 30 FPS 以上。当我 运行 我的代码:
import serial
import numpy
import matplotlib.pyplot as plt #import matplotlib library
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *
import matplotlib.animation
import time
ser = serial.Serial('COM7',9600,timeout=5)
ser.flushInput()
time.sleep(5)
ser.write(bytes(b's1000'))
x=list()
y=list()
z=list()
#plt.ion()
fig = plt.figure(figsize=(16,12))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(x,y,z, c='r',marker='o')
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
def generate():
while True:
try:
ser_bytes = ser.readline()
data = str(ser_bytes[0:len(ser_bytes)-2].decode("utf-8"))
xyz = data.split(", ")
dx = float(xyz[0])
dy = float(xyz[1])
dz = float(xyz[2].replace(";",""))
x.append(dx);
y.append(dy);
z.append(dz);
graph._offset3d(x,y,z, c='r',marker='o')
except:
print("Keyboard Interrupt")
ser.close()
break
return graph,
ani = matplotlib.animation.FuncAnimation(fig, generate(), interval=1, blit=True)
plt.show()
我收到以下错误:
Traceback (most recent call last):
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1026, in _start
self._init_draw()
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1750, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
TypeError: 'tuple' object is not callable
Traceback (most recent call last):
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1308, in _handle_resize
self._init_draw()
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1750, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "C:\Users\bunti\AppData\Local\Programs\Python\Python36-32\lib\site-packages\matplotlib\animation.py", line 1772, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
TypeError: 'tuple' object is not callable
我从连接到 Arduino 的激光雷达模块接收 x、y、z 坐标,Arduino 通过串行方式将坐标发送到 Python 脚本。
您的代码可能存在的问题是动画函数 (generate
) 不应该 运行 在无限循环中。此外,您应该将对该函数的引用传递给 FuncAnimate
,但您实际上是在调用该函数(即您需要省略 FuncAnimation(..., generate, ...)
第二个问题是,当 graph._offset3d
只是一个列表元组时,您将其视为一个函数。您应该为其分配一个新的元组,而不是尝试 调用 函数(我相信这是错误消息所暗示的)。
我简化了您的代码,以下工作正常:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
def update_lines(num):
dx, dy, dz = np.random.random((3,)) * 255 * 2 - 255 # replace this line with code to get data from serial line
text.set_text("{:d}: [{:.0f},{:.0f},{:.0f}]".format(num, dx, dy, dz)) # for debugging
x.append(dx)
y.append(dy)
z.append(dz)
graph._offsets3d = (x, y, z)
return graph,
x = [0]
y = [0]
z = [0]
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(x, y, z, color='orange')
text = fig.text(0, 1, "TEXT", va='top') # for debugging
ax.set_xlim3d(-255, 255)
ax.set_ylim3d(-255, 255)
ax.set_zlim3d(-255, 255)
# Creating the Animation object
ani = animation.FuncAnimation(fig, update_lines, frames=200, interval=50, blit=False)
plt.show()