使用Python mplotlib通过串行数据对3D散点图进行动画处理 [英] Animating 3D scatter plot using Python mplotlib via serial data

查看:98
本文介绍了使用Python mplotlib通过串行数据对3D散点图进行动画处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在python中使用mplotlib为3D散点图制作动画.我能够绘制数据图并每次重绘,但这导致帧速率小于1 FPS,并且我需要扩展到30 FPS以上.当我运行我的代码时:

I am trying to animate a 3D scatter plot using mplotlib in Python. I am able to graph the data and redraw every time, but this results in a frame rate of less than 1 FPS, and I need to scale to upwards of 30 FPS. When I run my code:

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坐标,该模块通过串行将坐标发送到Python脚本.

I am receiving x, y, z coordinates from a lidar module connected to an Arduino, which sends the coordinates over serial to the Python script.

推荐答案

您的代码可能存在的问题是,动画功能(generate)不应在无限循环中运行.此外,您应该将对该函数的引用传递给FuncAnimate,但是您要调用该函数(即,您需要省略FuncAnimation(..., generate, ...)

A possible problem with your code is that the animation function (generate) is not supposed to run in an infinite loop. Furthermore, you are supposed to pass a reference to that function to FuncAnimate, but instead you are calling the function (i.e. you need to omit the parentheses in FuncAnimation(..., generate, ...)

第二个问题是,当graph._offset3d只是一个列表的元组时,您会将其视为函数.您应该为其分配一个新的元组,而不要尝试调用该函数(我相信这是错误消息所指的含义).

The second problem is that you are treating graph._offset3d as if it was a function, when it is merely a tuple of lists. You should assign a new tuple to it, instead of trying to call the function (which I believe is what the error message alludes to).

我简化了您的代码,以下代码可以正常工作:

I simplified your code and the following works fine:

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散点图进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆