Making an updating plot of a ROS input

96 views Asked by At

Is there any "good" way to create a updating plot with the input from a ros node in python.

I have the following working code, but I am looking for a better solution, as it is very base stylistically, e.g. creating a new node on every iteration of the loop:

import numpy as np
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import matplotlib.pyplot as plt
import time


bridge = CvBridge()


fig = plt.figure()
ax = fig.add_subplot(111)
array = np.random.random((128,128))
im = ax.imshow(array)
plt.show(block=False)
rdi= np.ones((32,32))

len = 100

def saveit(Data):
    global rdi
    image = bridge.imgmsg_to_cv2(Data)
    rdi = np.asarray(image)

def listener():
    rospy.init_node('dataSaver', anonymous = False)
    rospy.Subscriber('range_doppler_abs', Image,saveit)




for i in range (len):
    listener()
    rdi = rdi/(np.max(rdi))
    im.set_array(rdi)
    fig.canvas.draw()
    time.sleep(0.1)

I am trying to get it into proper shape, but with my best attempts so far, I get a segmentation fault, or the plot doesn't update at all.

1

There are 1 answers

0
tridentifer On

For anybody reading this question later, I have found a more satisfying, while still probably not great answer. It works fine and doesn't create a new node for every instance it is listening to the sensor.

#!/usr/bin/env python3 
import numpy as np
from matplotlib import pyplot as plt
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge

fig = plt.figure()    #Seems to be a little bit faster if fig is outside class

class Plotter:
  def __init__(self):
    #self.fig = plt.figure()
    self.a = np.random.random((32,32))*10
    self.plot= plt.imshow(self.a)           #Imshow creates type of figure we wish
    self.bridge = CvBridge()
    

  def plot_x(self,msg):
    self.a = self.bridge.imgmsg_to_cv2(msg)
    self.plot.set_data(self.a)
    plt.draw()

if __name__ == '__main__':
  rospy.init_node("watcher")
  obj = Plotter()
  rospy.Subscriber('rdi', Image,obj.plot_x)
  plt.show(block=True)
  rospy.spin()