I am using a RPLidar A1 in python.
it looks pretty perfect and this is my code below
it is originally from https://github.com/SkoltechRobotics/rplidar/blob/master/examples/animate.py#L1
GitHub.
#!/usr/bin/env python3
'''Animates distances and measurment quality'''
from rplidar import RPLidar
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
PORT_NAME = '/dev/ttyUSB0'
DMAX = 4000
IMIN = 0
IMAX = 50
def update_line(num, iterator, line):
scan = next(iterator)
offsets = np.array([(np.radians(meas[1]), meas[2]) for meas in scan])
line.set_offsets(offsets)
intens = np.array([meas[0] for meas in scan])
line.set_array(intens)
return line,
def run():
lidar = RPLidar(PORT_NAME)
fig = plt.figure()
ax = plt.subplot(111, projection='polar')
line = ax.scatter([0, 0], [0, 0], s=5, c=[IMIN, IMAX],
cmap=plt.cm.Greys_r, lw=0)
ax.set_rmax(DMAX)
ax.grid(True)
iterator = lidar.iter_scans()
ani = animation.FuncAnimation(fig, update_line,
fargs=(iterator, line), interval=50)
plt.show()
lidar.stop()
lidar.disconnect()
if __name__ == '__main__':
run()
but it has issues like this picture.
I think that it is because of something buffer. But no idea how to handle this one. if you help me about this issues, I really appreciate of it.
I have no idea why this is happened please let me know Thank you!
From the RPLidar documentation: https://github.com/SkoltechRobotics/rplidar/blob/master/rplidar.py
The iter_scans() [and iter_measurments()] functions have a default parameter of max_buf_meas. This defaults to 500. It looks like you're filling this buffer too quickly.
I suggest giving the iter_scans() call a buffer argument that is greater than the number your program is giving you, perhaps 800 or 1000.
Related
I have to set blit = true, since the plotting is much faster. But after animation (repeat = false), if I use zoom in the figure, the figure will just disappear. I need to keep the last frame so that I can zoom in the last figure.
Thanks!
One work around is to initialize the animation using the last frame. The obvious down side is you have to precompute the last frame. Adapting this example would be
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))
cnt = 50 # Define so we know what the last frame will be.
def init():
# Note the function is the same as `animate` with `i` set to the last value
line.set_ydata(np.sin(x + cnt / 100))
return line,
def animate(i):
line.set_ydata(np.sin(x + i / 100)) # update the data.
return line,
ani = animation.FuncAnimation(
fig, animate, init_func=init, interval=2, blit=True, save_count=cnt)
ani.save("mwe.mov")
fig.savefig("mwe.png")
I have a function that outputs return (x, y) and i would like to animate the x,y pair, from beginning to end. E.g. such that the line 'develops over time'.
This is what my output looks like:
x, y = stephan()
plt.plot(x,y)
And when I try to use a snippit of animation code:
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
def init():
line.set_data([], [])
return line,
def animate(i):
x, y = stephan()
line.set_data(x, y[i])
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
I get this quite boring output:
It is plotting something, but certainly not the x,y output. I think that I might be using the animate or init function wrongly? And strangely enough, I haven't been able to find any code that does this quite simply.
If the call to stephan returns two floats, y[i] does not make any sense. Furthermore you would want to store the output in a list, to obtain a line and not a single dot per frame.
A working example could look like this
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
class Stephan():
i=0
def __call__(self):
self.i += 0.02
return self.i, np.random.randn(1)
stephan = Stephan()
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
def init():
line.set_data([], [])
return line,
X = []
def animate(i):
x, y = stephan()
X.append((x,y))
line.set_data(zip(*X))
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
plt.show()
Alternatively, if stephan returns two lists of values, you could directly set those lists as data to the line.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
class Stephan():
x=[0]
y=[1]
def __call__(self):
self.x.append(self.x[-1]+0.02)
self.y.append(np.random.randn(1))
return self.x, self.y
stephan = Stephan()
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
def init():
line.set_data([], [])
return line,
def animate(i):
x, y = stephan()
line.set_data(x,y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
plt.show()
I'm trying to create a plot in Python where the data that is being plotted gets updated as my simulation progresses. In MATLAB, I could do this with the following code:
t = linspace(0, 1, 100);
figure
for i = 1:100
x = cos(2*pi*i*t);
plot(x)
drawnow
end
I'm trying to use matplotlib's FuncAnimation function in the animation module to do this inside a class. It calls a function plot_voltage which recalculates voltage after each timestep in my simulation. I have it set up as follows:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def __init__(self):
ani = animation.FuncAnimation(plt.figure(2), self.plot_voltage)
plt.draw()
def plot_voltage(self, *args):
voltages = np.zeros(100)
voltages[:] = np.nan
# some code to calculate voltage
ax1 = plt.figure(2).gca()
ax1.clear()
ax1.plot(np.arange(0, len(voltages), 1), voltages, 'ko-')`
When my simulation runs, the figures show up but just freeze. The code runs without error, however. Could someone please let me know what I am missing?
Here is a translation of the matlab code into matplotlib using FuncAnimation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
t = np.linspace(0, 1, 100)
fig = plt.figure()
line, = plt.plot([],[])
def update(i):
x = np.cos(2*np.pi*i*t)
line.set_data(t,x)
ani = animation.FuncAnimation(fig, update,
frames=np.linspace(1,100,100), interval=100)
plt.xlim(0,1)
plt.ylim(-1,1)
plt.show()
In the following code I have two separate animations and I have plotted them in a two separate subplots. I want both of them to run in a single plot instead of this. I have tried the approach explained below but it is giving me issues as explained below. Please help
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time as t
x = np.linspace(0,5,100)
fig = plt.figure()
p1 = fig.add_subplot(2,1,1)
p2 = fig.add_subplot(2,1,2)
def gen1():
i = 0.5
while(True):
yield i
i += 0.1
def gen2():
j = 0
while(True):
yield j
j += 1
def run1(c):
p1.clear()
p1.set_xlim([0,15])
p1.set_ylim([0,100])
y = c*x
p1.plot(x,y,'b')
def run2(c):
p2.clear()
p2.set_xlim([0,15])
p2.set_ylim([0,100])
y = c*x
p2.plot(x,y,'r')
ani1 = animation.FuncAnimation(fig,run1,gen1,interval=1)
ani2 = animation.FuncAnimation(fig,run2,gen2,interval=1)
fig.show()
I tried creating a single subplot instead of p1 and p2 and have both the plots graphed in that single subplot. That is just plotting one graph and not both of them. As far as I can say it is because one of them is getting cleared right after it is plotted.
How do I get around this problem?
As you do not show the code that is actually producing the problem, it's hard to tell where the problem lies.
But to answer the question of how to animate two lines in the same axes (subplot), we can just get rid of the clear() command and update the lines, instead of producing a new plot for every frame (which is more efficient anyways).
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(0,15,100)
fig = plt.figure()
p1 = fig.add_subplot(111)
p1.set_xlim([0,15])
p1.set_ylim([0,100])
# set up empty lines to be updates later on
l1, = p1.plot([],[],'b')
l2, = p1.plot([],[],'r')
def gen1():
i = 0.5
while(True):
yield i
i += 0.1
def gen2():
j = 0
while(True):
yield j
j += 1
def run1(c):
y = c*x
l1.set_data(x,y)
def run2(c):
y = c*x
l2.set_data(x,y)
ani1 = animation.FuncAnimation(fig,run1,gen1,interval=1)
ani2 = animation.FuncAnimation(fig,run2,gen2,interval=1)
plt.show()
I'm new to python, matplotlib, and animation.
I've not been able to find a clear, detailed description of
animation.FuncAnimation(, , , , , , ......), so I've been trying to modifiy examples I've found. What are all the allowed parameters for FuncAnimation in English?
I want to produce a graph of dots shown one at a time with a time about 1 second between appearances.
Here's my current code that just produces a continuous curve after a delay:
def init():
line1.set_data([],[],'og')
return line1,
def animate(x):
x = np.linspace(0, 650, num=20, endpoint = True) #start at 0, stop at 650, number of values
y1 = (v0_y/v0_x)*x - (g/2)*(x/v0_x)**2
line1.set_data(x, y1)
time.sleep(1)
return line1,
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=3000, blit=True)
All suggestions appreciated!
You can check the documentation of FuncAnimation here, and this is an example code that does what you want:
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
xs = np.linspace(0, 650, num=20, endpoint = True)
ys = np.random.rand(20)
fig = plt.figure()
line1, = plt.plot([],[],'og')
plt.gca().set_xlim(0,650)
def init():
return line1,
def animate(i):
line1.set_data(xs[:i], ys[:i])
return line1,
anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1000, blit=True)
plt.show()
Output window: