Hello,
I want to plot real-time flight control data to get a better and faster understanding of the performance of our flight controllers.
The incoming data stream might be decoded in a C-function (because it already exists).
But then I would like to plot one to three data streams in Julia with an update rate of about 30 Hz. Just an oscilloscope like plot.
In addition it would be nice to select the data stream(s) in the GUI.
Which plotting package might be the best choice?
Uwe
Perhaps this could be useful:
I think you’ll get highest performance and frame rates from Makie, but I think GR is also able to do pretty well. I believe InspectDR is designed to be quite fast, but I haven’t used it.
Depending on the size of the data you are plotting, PlotlyJS might also work for you. I recently used the react!
function in PlotlyJS to in-place update an existing plot and Interact as an interface, and I was surprised at how responsive it was. It was updating at least at 30Hz.
Thanks a lot for all your responses! I will try some of your suggestions soon.
I was wondering how InspectDR would handle this myself… so I made a small test:
using InspectDR
using Colors
function getmeasdata(t, φ)
sigA = sin.(t .+ φ)
sigB = cos.(t .+ φ)
return (sigA, sigB)
end
#Build general structure of animation plot
function buildanimplot()
NPOINTS = 1000
NCYCLES = 2 #To display
RED = RGB24(1, 0, 0)
GREEN = RGB24(0, 1, 0)
BLUE = RGB24(0, 0, 1)
#collect: InspectDR does not take AbstractArray:
t = collect(range(0, stop=NCYCLES*2pi, length=NPOINTS))
(sigA, sigB) = getmeasdata(t, 0)
#Using Plot2D simplified "template" constructor:
p = InspectDR.Plot2D(:lin, [:lin, :lin],
title = "Measured Data", xlabel = "time (s)",
ylabels = ["Amplitude (V)", "Amplitude (V)"]
)
p.layout[:enable_legend] = true
wfrmA = add(p, t, sigA, id="Signal A", strip=1)
wfrmA.line = line(color=RED, width=2)
wfrmB = add(p, t, sigB, id="Signal B", strip=2)
wfrmB.line = line(color=BLUE, width=2)
gplot = display(InspectDR.GtkDisplay(), p)
return (gplot, t, wfrmA, wfrmB)
end
#Update animated plot in "real time":
function testanimplot()
DURATION = 5 #sec
NSTEPS = 1000
RADPERSEC = 2pi
tstep = DURATION/NSTEPS
ϕstep = RADPERSEC * tstep
(gplot, t, wfrmA, wfrmB) = buildanimplot()
@time begin #Curious to see how long it actually takes
for ϕ in range(0, step=ϕstep, length=NSTEPS)
sleep(DURATION/NSTEPS)
(sigA, sigB) = getmeasdata(t, ϕ)
wfrmA.ds.y = sigA
wfrmB.ds.y = sigB
InspectDR.refresh(gplot)
end
end
return gplot
end
gplot = testanimplot()
This might make it easier to see if InspectDR is adequate for your task…
How did you do it? Hints will be much appreciated.
The general premise is to keep your trace objects that are used in constructing the plot, update them inplace, and then call react!
with your plot objects and your (modified) traces. Here’s an example:
using PlotlyJS
t = 1:25
x1 = sin.(t./(pi))
x2 = rand(25) .+ 2
trace1 = scatter(;x=t, y=x1)
trace2 = scatter(;x=t, y=x2)
l = Layout()
p = plot([trace1, trace2], l)
for i in 1:100
trace1[:y] .= sin.((t .+ i) ./ pi)
trace2[:y] .= rand(25) .+ 2
react!(p, [trace1, trace2], l)
sleep(0.1)
end
That’s cool.
Nice. That is pretty much what I ended up doing, except that I thought it too much work to sort through existing traces to change them up. I just regenerated the traces from scratch every time they needed to be plotted.
Now the trickier part: Make the plot respond to user input during the simulation/plotting.