How to plot pointcloud2 in matplotlib - matplotlib

I have a sensor_msgs/PointCloud2 with [x,y,z] and how can I plot it in real-time in matplotlib like this code here. I already changed the type from Odometry to pointcloud2 but I don't know what to change in odom_callback or how to change the code in order to plot it in matplotlib. Can someone has an idea how to plot pointcloud2 in matplotlib
import matplotlib.pyplot as plt
import rospy
import tf
from sensor_msgs.msg import PointCloud2
from tf.transformations import quaternion_matrix
import numpy as np
from matplotlib.animation import FuncAnimation
class Visualiser:
def __init__(self):
self.fig, self.ax = plt.subplots()
self.ln, = plt.plot([], [], 'ro')
self.x_data, self.y_data = [] , []
def plot_init(self):
self.ax.set_xlim(0, 10000)
self.ax.set_ylim(-7, 7)
return self.ln
def getYaw(self, pose):
quaternion = (pose.orientation.x, pose.orientation.y, pose.orientation.z,
pose.orientation.w)
euler = tf.transformations.euler_from_quaternion(quaternion)
yaw = euler[2]
return yaw
def odom_callback(self, msg):
yaw_angle = self.getYaw(msg.pose.pose)
self.y_data.append(yaw_angle)
x_index = len(self.x_data)
self.x_data.append(x_index+1)
def update_plot(self, frame):
self.ln.set_data(self.x_data, self.y_data)
return self.ln
rospy.init_node('publisher_node')
vis = Visualiser()
sub = rospy.Subscriber('/scan3dd', PointCloud2, vis.odom_callback)
ani = FuncAnimation(vis.fig, vis.update_plot, init_func=vis.plot_init)
plt.show(block=True)

Related

Why does this plot not update ? (matplotlib)

Code below, I want to write a code that updates its function by cearing the axes and assigning new plots. It works when I only have one plot, but doesnt when I use subplots()...
Thanks
import numpy as np
import matplotlib.pyplot as plt
import time
fig , ax = plt.subplots(1,2)
x = np.linspace(0,10,10)
alpha = 0.70
def sin(x):
return np.sin(alpha*x)
def lin(x):
return alpha*x
for i in range(5):
ax[0].clear()
ax[1].clear()
ax[0].plot(x,lin(x), marker='o', label = str(i))
ax[1].plot(x,sin(x), marker='o')
fig.legend()
plt.show()
alpha = alpha**2
time.sleep(0.5)

Why sparklines are outside of table as expected?

Bonjour,
"sparkline" does not work in my code.
Already, I didn't manage to install it. So, I found a function that I call "sparkline_test. Nevertheless, the images that should be integrated in the table are outside. Something is wrong.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from io import BytesIO
from itertools import islice
import seaborn as sns
import base64
I cannot import sparklines:
#import sparklines
df = sns.load_dataset('titanic')
def percentile_90(x):
return x.quantile(.9)
from scipy.stats import trim_mean
def trim_mean_10(x):
return trim_mean(x, 0.1)
def largest(x):
return x.nlargest(1)
def sparkline_str(x):
bins=np.histogram(x)[0]
sl = ''.join(sparklines(bins))
return sl
def sparkline_test(data, figsize=(4,0.25),**kwags):
data = list(data)
fig,ax = plt.subplots(1,1,figsize=figsize,**kwags)
ax.plot(data)
for k,v in ax.spines.items():
v.set_visible(False)
ax.set_xticks([])
ax.set_yticks([])
plt.plot(len(data)-1, data[len(data)-1], 'r.')
ax.fill_between(range(len(data)), data, len(data)*[min(data)], alpha=0.1)
img = BytesIO()
plt.savefig(img, transparent=True, bbox_inches='tight')
img.seek(0)
plt.show()
# plt.close()
return base64.b64encode(img.read()).decode("utf-8")
def sparkline_str(x):
bins=np.histogram(x)[0]
sl = ''.join(sparkline_test(bins))
return sl
agg_func_largest = {
'fare': [percentile_90, trim_mean_10, largest, sparkline_test]
#'fare': [percentile_90, trim_mean_10, largest]
}
df.groupby(['class', 'embark_town']).agg(agg_func_largest)
that produces:
What is expected is:
Something is wrong....But what?
Do you have any idea?
Regards,
Atapalou

Matplotlib line chart animation

I am trying to animate a simple line chart with 2 equal arrays. I've seen some guides online but honestly, I'm not sure what I'm doing here, am I close to the solution?
I'm looking for this: https://miro.medium.com/max/1126/1*j0LxVQPbwtQDpL17TH9gZw.gif
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
x = np.array([1,2,3,4,5,6,7,8])
y = np.array([6,9,12,42,50,62,76,82])
fig = plt.figure()
ax = plt.axes(xlim=(1, 8), ylim=(6, 82))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
def animate(i):
line.set_ydata(x[i:])
line.set_xdata(y[i:])
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=200, interval=20, blit=True)
anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()
We are changing the way the data is set up. And I changed the number of frames to 9 because the number of data is 8. In addition, I used PIL to create GIF images, so please correct it.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from IPython.display import HTML
from matplotlib.animation import PillowWriter
x = np.array([1,2,3,4,5,6,7,8])
y = np.array([6,9,12,42,50,62,76,82])
fig = plt.figure()
ax = plt.axes(xlim=(1, 8), ylim=(6, 82))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
def animate(i):
line.set_data(x[:i],y[:i])
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=9, interval=200, blit=True)
# anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
# plt.show()
anim.save('plot_ani.gif', writer='pillow')

How do I animate a circle to move horizontally?

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
xvalues = np.arange(4000000, 6000000+1000, 1000).tolist()
yvalues = [5000000]*2001
Acc_11 = xvalues
Acc_12 = yvalues
fig = plt.figure(figsize = (5,5))
axes = fig.add_subplot(111)
axes.set_xlim((0, 10000000))
axes.set_ylim((0, 10000000))
point, = plt.Circle((4000000, 5000000), 60000, color = "black")
def ani(coords):
point.set_data([coords[0]],[coords[1]])
return point
def frames():
for acc_11_pos, acc_12_pos in zip(Acc_11, Acc_12):
yield acc_11_pos, acc_12_pos
ani = FuncAnimation(fig, ani, frames=frames, interval=10)
plt.show()
Im getting TypeError: 'Circle' object is not iterable. What I need to do? The size of a circle must be changable and related to axes, so matplotlib circle is the only option (I guess).
Here's a possible solution (assuming you are running in a jupyter notebook cell):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
xvalues = np.arange(4000000, 6000000+1000, 1000).tolist()
yvalues = [5000000]*2001
Acc_11 = xvalues
Acc_12 = yvalues
fig = plt.figure(figsize = (5,5))
axes = fig.add_subplot(111)
axes.set_xlim((0, 10000000))
axes.set_ylim((0, 10000000))
point = plt.Circle((4000000, 5000000), 60000, color = "black")
def init():
point.center = (5, 5)
axes.add_patch(point)
return point,
def ani(i):
point.center = (Acc_11[i],Acc_12[i])
return point
anim = FuncAnimation(fig,
ani,
init_func=init,
frames=200, #len(Acc_11),
interval=10)
HTML(anim.to_html5_video())
You may want to change frames=200 to frames=len(Acc_11) but it will take a while to run.

Matplotlib scalarformatter not converting y-ticks to standard form

I am trying to use ScalarFormatter to convert my y-axis ticks into standard form, but after much experimenting I'm experiencing no success and I can't figure out why. MWE:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import scipy.constants as const
k = 1/(4*np.pi*const.epsilon_0)
def force_e(q_1,q_2,x):
return k*q_1*q_2/x**2
d = 10
delta = 0.1*d
x = np.linspace(0+delta,d-delta,1000)
q1 = 2e-6
q2 = -2e-6
q = 1e-9
F = force_e(q1,q,x) - force_e(q2,q,d-x)
fig,ax1 = plt.subplots(1, figsize=(6,6))
ax1.plot(x, F)
ax1.yaxis.set_major_formatter(mpl.ticker.ScalarFormatter(useMathText=True))
ax1.set_xlabel("Separation $r$ (m)")
ax1.set_ylabel("Force $F$ (N)")
plt.tight_layout()
plt.show()
It produces a figure as so:
where as I would like it to display 1.75x10^5 etc.