ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
2

plotting real time data

asked 2017-06-26 09:52:49 -0500

linusnie gravatar image

updated 2017-06-30 04:15:39 -0500

I want process the data from some ros nodes and make a real time plot, preferably using matplotlib. What is the easiest way to do this?

For example if I would like plot the average of two values in the ros network, or add a legend to the plot. I know about rqt_plot, but its usefulness is very limited since it can only plot already defined messages.. and you can't even change the axis limits afaik!

Any tips? The best thing would be if there was a way to continually update a matplotlib figure and have it displayed as the roscore is running.

edit retag flag offensive close merge delete

Comments

3

Take a look at https://github.com/facontidavide/Plot... - I haven't tried it yet but I'd like to hear if it addresses some of your needs.

lucasw gravatar image lucasw  ( 2017-06-26 17:32:38 -0500 )edit

There is an infinity of answers on stackoverflow treating the continuous update of a matplotlib figure.

Mehdi. gravatar image Mehdi.  ( 2017-06-30 02:46:33 -0500 )edit

5 Answers

Sort by ยป oldest newest most voted
3

answered 2017-06-30 02:32:53 -0500

linusnie gravatar image

updated 2017-06-30 02:35:40 -0500

I ended up doing the following. It works in real time as long as pyplot can keep up with the messages.

#!/usr/bin/env python 
import numpy as np
from matplotlib import pyplot as plt
import rospy
from qualisys.msg import Subject

def plot_x(msg):
    global counter
    if counter % 10 == 0:
        stamp = msg.header.stamp
        time = stamp.secs + stamp.nsecs * 1e-9
        plt.plot(msg.position.y, msg.position.x, '*')
        plt.axis("equal")
        plt.draw()
        plt.pause(0.00000000001)

    counter += 1

if __name__ == '__main__':
    counter = 0

    rospy.init_node("plotter")
    rospy.Subscriber("position_measurements", Subject, plot_x)
    plt.ion()
    plt.show()
    rospy.spin()
edit flag offensive delete link more

Comments

I, ve tried this program, but I have an error

    Traceback (most recent call last):
  File "./subscriber_sniffer.py", line 5, in <module>
    from qualisys.msg import Subject
ImportError: No module named qualisys.msg

Have you got any suggestion?

dei gravatar image dei  ( 2021-03-05 02:55:15 -0500 )edit

Yes, because you do not have probably a ROS package named qualisys. You probably also do not need it because to try this code, you need a node that is publishing messages of the type Subject from this package qualisys. I replaced that line with nav_msgs/Odometry like this:

from nav_msgs.msg import Odometry

This is because the things I want to live plot as are published on the topic /odom of the above mentioned message type. Remeber to also change the position_measurements with your topic name in rospy.Subscriber(...)

shrini96 gravatar image shrini96  ( 2023-05-21 17:28:33 -0500 )edit

@linusnie the solution works beautifully. Thanks a lot.

shrini96 gravatar image shrini96  ( 2023-05-21 17:29:13 -0500 )edit
5

answered 2018-01-30 05:23:23 -0500

Markus gravatar image

There are many tools to plot.

- rqt_plot

- rqt_multiplot (from ethz) tool is quite nice to use (compared to rqt_plot)

-plot_juggler this is my favourite tool its so fast plotting data and so easy to use! Try it yourself!

Install:

sudo apt-get install ros-kinetic-plotjuggler

Run it:

  • rosrun plotjuggler PlotJuggler
  • Go to streaming and start ros_topic_streaming
  • simply select your topics you wanna stream

Start in launch file:

<!-- start plotjuggler -->
<node pkg="plotjuggler" type="PlotJuggler" name="my_plot_Juggler" args="" />

If anyone knows how to start from launch file a saved layout.xml Would be great for sharing :)

edit flag offensive delete link more

Comments

Hi, thanks for recommending PlotJuggler (I am the author). I super appreciate it.

PlotJuggler uses old fashion command line arguments instead os ros params. Display them with -h. You can do:

<node pkg="plotjuggler" type="PlotJuggler" name="my_plot_Juggler" args="--layout your_filename"/>

Davide Faconti gravatar image Davide Faconti  ( 2018-01-30 05:54:40 -0500 )edit

Yeah I saw that --layout our just -l option but it does not work for me If I start gazebo paused.I get cannot find curve with ... error. And if I just run the sim. for a small amount of time and then try to load my layout I get the streamer named ROS Topic Streamer cannot be loaded.

Markus gravatar image Markus  ( 2018-01-31 00:18:50 -0500 )edit

If you can describe in more detail the problem and/or the desired behavior here, https://github.com/facontidavide/Plot... I will be happy to improve it.

Davide Faconti gravatar image Davide Faconti  ( 2018-02-02 03:33:30 -0500 )edit
3

answered 2017-06-27 02:02:26 -0500

I did liveplotting in the past in two ways:

Your prefered way is the matplotlib so thats pretty easy and I explain a little bit more:

There you need a animation.FuncAnimation. It makes an animation by repeatedly calling a function/method. You can read more here.

Furter in the repeatedly called function you should do something like:

xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)

so there you append new data and than set it. What you now need to do different is that you setup a ROS Subscriber to your data you want to publish and in the callback function/method you need to append the new data and just set in the repeatedly called function the new data. Thats only a close look about how you can do it to give you an idea.

The other way is using c++ and writing for example a rviz plugin with QT. I prefere here the QCustomPlot for live plotting. But thats a little bit tricky and needs more time when you have no idea about QT. But for me it generates better looking plots and when you are used to it its very easy too.

When you need further help please ask! It isnt too detailed. Just to give you an idea.

edit flag offensive delete link more

Comments

this works! but I've always found FuncAnimation to be cumbersome to work with. If anyone has other ideas I'm still interested

linusnie gravatar image linusnie  ( 2017-06-27 03:19:14 -0500 )edit

qcustomplot is amazing!

user23fj239 gravatar image user23fj239  ( 2020-03-28 16:28:17 -0500 )edit
1

answered 2020-08-25 08:22:04 -0500

GPrathap gravatar image

Since this is an old post and still seems to be active in the community, I am going to provide an example, in general, how can we do real-time plotting. Here I used matplotlib FuncAnimation function.

import matplotlib.pyplot as plt
import rospy
import tf
from nav_msgs.msg import Odometry
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('lidar_visual_node')
vis = Visualiser()
sub = rospy.Subscriber('/dji_sdk/odometry', Odometry, vis.odom_callback)

ani = FuncAnimation(vis.fig, vis.update_plot, init_func=vis.plot_init)
plt.show(block=True)
edit flag offensive delete link more
0

answered 2017-06-26 12:20:35 -0500

Airuno2L gravatar image

I would recommend rqt_plot. Don't forget you can plot the std_msgs. Almost anything can be represented by them. It sounds like what you want to plot can be a Float32 message.

Also, click on the green checkmark on the rqt_plot gui above the plot area to access the axis max/min settings.

edit flag offensive delete link more

Comments

It's a bit time consuming to have to readjust axis settings manually for different experiments. I am really looking for a way to customise plots programmatically. Also, afaik there is no way to change the x-axis in an rqt plot, like if I want to plot x/y coordinates or motor input vs speed.

linusnie gravatar image linusnie  ( 2017-06-26 12:30:29 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2017-06-26 09:52:49 -0500

Seen: 20,134 times

Last updated: Aug 25 '20