-
-
Save cserteGT3/4ebe5df6ade2bc6183f47b1bbbedc080 to your computer and use it in GitHub Desktop.
An attempt to create real time plotting with Makie. Description is at the Julia Discourse.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Pkg | |
Pkg.activate(".") | |
using Sockets | |
using Logging | |
using DelimitedFiles | |
using Makie, AbstractPlotting | |
using Observables: off | |
# Enables the socket reading loop. | |
const FORCE_SOCKET_EN = Node(true) | |
# Stores the last received string. | |
const force_string = Node("[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]") | |
# latest plot time. | |
const lastUpdate = Node(time_ns()); | |
function serverTask() | |
FORCE_SOCKET_EN[] = true | |
@info "Server is running on localhost: $SERVER_PORT" | |
server = listen(SERVER_PORT) | |
socket = accept(server) | |
close(server) | |
@info "Accepted: $(getpeername(socket)[1]). Server is closed." | |
while isopen(socket) && FORCE_SOCKET_EN[] | |
force_string[] = readline(socket) | |
end | |
close(socket) | |
@info "Socket closed, task is finished." | |
end | |
# Size of the plotted dataset | |
MAX_SIZE = 1250; | |
#= | |
This part throws some DimensionMismatch exception at s1 = lines(fxNode); | |
and could not find why, so changed to rand. | |
FxV = Array{Float64}(undef, MAX_SIZE); | |
FyV = Array{Float64}(undef, MAX_SIZE); | |
FzV = Array{Float64}(undef, MAX_SIZE); | |
TxV = Array{Float64}(undef, MAX_SIZE); | |
TyV = Array{Float64}(undef, MAX_SIZE); | |
TzV = Array{Float64}(undef, MAX_SIZE); | |
=# | |
# Arrays storing the data | |
FxV = rand(MAX_SIZE); | |
FyV = rand(MAX_SIZE); | |
FzV = rand(MAX_SIZE); | |
TxV = rand(MAX_SIZE); | |
TyV = rand(MAX_SIZE); | |
TzV = rand(MAX_SIZE); | |
tV = rand(MAX_SIZE); | |
fxNode = Node(FxV); | |
fyNode = Node(FyV); | |
fzNode = Node(FzV); | |
txNode = Node(TxV); | |
tyNode = Node(TyV); | |
tzNode = Node(TzV); | |
tvNode = Node(tV); | |
# subplots | |
s1 = lines(fxNode); | |
s2 = lines(fyNode); | |
s3 = lines(fzNode); | |
s4 = lines(txNode); | |
s5 = lines(tyNode); | |
s6 = lines(tzNode); | |
# put in an array to handle the axes and the limit updates easier | |
sArr = [s1, s2, s3, s4, s5, s6]; | |
yArr = ["Fx [N]", "Fy [N]", "Fz [N]", "Tx [Nm]", "Ty [Nm]", "Tz [Nm]"]; | |
# arrange into layout | |
scene = vbox(hbox(sArr[3], sArr[2], sArr[1]), hbox(sArr[6], sArr[5], sArr[4])); | |
# adding names for the axes | |
for i in 1:6 | |
sArr[i][Axis][:names][:axisnames] = ("Time [s]", yArr[i]); | |
end | |
# this function ensures that the arrays stay "fixed size" | |
function pushTo!(A, newX, maxSize) | |
if size(A, 1) < maxSize | |
push!(A, newX) | |
else | |
popfirst!(A) | |
push!(A, newX) | |
end | |
end | |
# minimum time between two updates | |
UPDATE_LAT = 200; #ms | |
# startup of the data acquisition - not used currently | |
startUp = time_ns(); | |
# updates the arrays based on the input string | |
function updateForceVec(message) | |
try | |
buf = IOBuffer(message[2:end-1]) | |
f = readdlm(buf, ',') | |
pushTo!(FxV, f[1], MAX_SIZE) | |
pushTo!(FyV, f[2], MAX_SIZE) | |
pushTo!(FzV, f[3], MAX_SIZE) | |
pushTo!(TxV, f[4], MAX_SIZE) | |
pushTo!(TyV, f[5], MAX_SIZE) | |
pushTo!(TzV, f[6], MAX_SIZE) | |
# get the current time | |
current_time = time_ns() | |
# save the time in seconds - not used currently | |
ttt = (current_time-startUp)/1000000000 | |
pushTo!(tV, ttt, MAX_SIZE) | |
# hand made throttle: | |
# if the latest message arrived later than UPDATE_LAT milisecs | |
# then the plot is updated | |
if (current_time-lastUpdate[])/1000000 > UPDATE_LAT | |
lastUpdate[] = current_time | |
end | |
catch y | |
@info "Failed to process input string!" | |
# only for debugging: | |
@show y | |
end | |
end | |
# update the plot nodes and the limits | |
function updatePlot(val) | |
fxNode[] = FxV | |
fyNode[] = FyV | |
fzNode[] = FzV | |
txNode[] = TxV | |
tyNode[] = TyV | |
tzNode[] = TzV | |
# update limits: | |
for i in 1:6 | |
AbstractPlotting.update_limits!(sArr[i]) | |
end | |
AbstractPlotting.update!(scene) | |
end | |
# subscribe the array updater function to the input string | |
h_input = on(updateForceVec, force_string) | |
# subscribe the plot updater function to the lastUpdate node | |
h_plot = on(updatePlot, lastUpdate) | |
############# | |
# RUN THESE # | |
############# | |
display(scene) | |
SERVER_PORT = 4001; | |
sT = Task(serverTask) | |
schedule(sT) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment