Skip to content

Commit

Permalink
Merge pull request #33 from JuliaRobotics/feat/3Q20/aniTtitle
Browse files Browse the repository at this point in the history
add dt to animation title
  • Loading branch information
dehann authored Sep 7, 2020
2 parents c390b86 + 59f84b7 commit a17903d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 54 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "FunctionalStateMachine"
uuid = "3e9e306e-7e3c-11e9-12d2-8f8f67a2f951"
keywords = ["state machine"]
desc = "Functional state machine with stepping and visualization tools."
version = "0.2.5"
version = "0.2.6"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
1 change: 1 addition & 0 deletions src/FunctionalStateMachine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export
StateMachine,
emptyState,
exitStateMachine,
getIterCount,
sandboxStateMachineStep,
getStateLabel,
histStateMachineTransitions
Expand Down
23 changes: 18 additions & 5 deletions src/StateMachine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,22 @@ usrdata = nothing
while st(usrdata); end
```
"""
function (st::StateMachine{T})(userdata::T=nothing;
breakafter::Function=exitStateMachine,
verbose::Bool=false,
iterlimit::Int=-1,
recordhistory::Bool=false ) where {T}
function (st::StateMachine{T})( userdata::T=nothing;
breakafter::Function=exitStateMachine,
verbose::Bool=false,
iterlimit::Int=-1,
recordhistory::Bool=false,
housekeeping_cb::Function=(st)->() ) where {T}
#
st.iter += 1
# verbose print to help debugging
!verbose ? nothing : println("FSM $(st.name), iter=$(st.iter) -- $(st.next)")
# early exit plumbing
retval = st.next != breakafter && (iterlimit == -1 || st.iter < iterlimit)
# record steps for later
recordhistory ? push!(st.history, (Dates.now(), st.iter, deepcopy(st.next), deepcopy(userdata))) : nothing
# user has some special situation going on.
housekeeping_cb(st)
st.next = st.next(userdata)
return retval
end
Expand All @@ -73,6 +79,13 @@ function exitStateMachine(dummy)
return emptyState
end

"""
$SIGNATURES
How many iterations has this `::StateMachine` stepped through.
"""
getIterCount(st::StateMachine) = st.iter

"""
$SIGNATURES
Expand Down
99 changes: 51 additions & 48 deletions src/StateMachineAnimation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@ function histGraphStateMachineTransitions(stateVisits, allStates::Vector{Symbol}
end


function renderStateMachineFrame(vg,
frame::Int;
title::String="",
viewerapp::String="eog",
fext::String="png",
engine::String="dot",
show::Bool=true,
folder::String="fsm_animation",
folderpath = "/tmp/$folder/",
timest::String="",
rmfirst::Bool=false )
function renderStateMachineFrame( vg,
frame::Int;
title::String="",
viewerapp::String="eog",
fext::String="png",
engine::String="dot",
show::Bool=true,
folder::String="fsm_animation",
folderpath = "/tmp/$folder/",
timest::String="",
rmfirst::Bool=false )
#
if rmfirst
@warn "removing contents of $(folderpath)"
Expand All @@ -113,7 +113,7 @@ function renderStateMachineFrame(vg,
fid = open("$folderpath/dotscript.sh","w")
str = "head -n `wc -l $dotfile | awk '{print \$1-1}'` $dotfile > $folderpath/tmpdot.dot"
println(fid, str)
println(fid, "echo \"graph [label=\\\"$title, #$step, $(timest)\\\", labelloc=t];\" >> $folderpath/tmpdot.dot")
println(fid, "echo \"graph [label=\\\"$title, $(timest)\\\", labelloc=t];\" >> $folderpath/tmpdot.dot")
println(fid, "echo \"}\" >> $folderpath/tmpdot.dot")
close(fid)
run(`chmod u+x $folderpath/dotscript.sh`)
Expand All @@ -128,10 +128,10 @@ function renderStateMachineFrame(vg,
return filepath
end

function setVisGraphOnState!(vg, vertid;
xlabel::String="",
appendxlabel::String="",
vertColor::AbstractString="red" )
function setVisGraphOnState!( vg, vertid;
xlabel::String="",
appendxlabel::String="",
vertColor::AbstractString="red" )
#
vg.vertices[vertid].attributes["fillcolor"] = vertColor
vg.vertices[vertid].attributes["style"] = "filled"
Expand All @@ -154,18 +154,18 @@ function clearVisGraphAttributes!(vg)
nothing
end

function drawStateTransitionStep(hist,
step::Int,
vg,
lookup::Dict{Symbol,Int};
title::String="",
viewerapp::String="eog",
fext::String="png",
engine::String="dot",
show::Bool=true,
folder::String="",
frame::Int=step,
vertColor::AbstractString="red" )
function drawStateTransitionStep( hist,
step::Int,
vg,
lookup::Dict{Symbol,Int};
title::String="",
viewerapp::String="eog",
fext::String="png",
engine::String="dot",
show::Bool=true,
folder::String="",
frame::Int=step,
vertColor::AbstractString="red" )
#

lbl = getStateLabel(hist[step][3])
Expand All @@ -179,26 +179,26 @@ function drawStateTransitionStep(hist,
# delete!(vert.attributes, "style")

# identify and set the node
xlabel = length(title) > 0 ? (xlabelbefore != nothing ? xlabelbefore*"," : "")*title : ""
xlabel = length(title) > 0 ? (xlabelbefore !== nothing ? xlabelbefore*"," : "")*title : ""
setVisGraphOnState!(vg, vertid, xlabel=xlabel, vertColor=vertColor )

# render state machine frame
filepath = renderStateMachineFrame(vg,
frame,
title=title,
viewerapp=viewerapp,
fext=fext,
engine=engine,
show=show,
folder=folder,
timest=string(split(string(hist[step][1]),'T')[end]),
rmfirst=false)
filepath = renderStateMachineFrame( vg,
frame,
title=title,
viewerapp=viewerapp,
fext=fext,
engine=engine,
show=show,
folder=folder,
timest=string(split(string(hist[step][1]),'T')[end]),
rmfirst=false)
#

# clean up the vg structure
fillcolorbefore == nothing ? delete!(vert.attributes, "fillcolor") : (vert.attributes["fillcolor"]=fillcolorbefore)
stylebefore == nothing ? delete!(vert.attributes, "style") : (vert.attributes["style"]=stylebefore)
xlabelbefore == nothing ? delete!(vert.attributes, "xlabel") : (vert.attributes["xlabel"]=xlabelbefore)
fillcolorbefore === nothing ? delete!(vert.attributes, "fillcolor") : (vert.attributes["fillcolor"]=fillcolorbefore)
stylebefore === nothing ? delete!(vert.attributes, "style") : (vert.attributes["style"]=stylebefore)
xlabelbefore === nothing ? delete!(vert.attributes, "xlabel") : (vert.attributes["xlabel"]=xlabelbefore)

return filepath
end
Expand Down Expand Up @@ -398,8 +398,8 @@ end
# @async run(`totem /tmp/caesar/csmCompound/out.ogv`)
# draw_more_cb(::Tuple, ::Int, ::String)
function animateStateMachineHistoryIntervalCompound(hists::Dict{Symbol, Vector{Tuple{DateTime, Int, <: Function, T}}};
interval::Int=2, # frames
# frames::Int=100,
easyNames::Dict{Symbol,N}=Dict{Symbol,Nothing}(),
interval::Int=2,
folderpath="/tmp/animatestate",
title::String="",
show::Bool=false,
Expand All @@ -408,7 +408,7 @@ function animateStateMachineHistoryIntervalCompound(hists::Dict{Symbol, Vector{T
draw_more_cb::Function=(x...)->(),
fsmColors::Dict{Symbol,String}=Dict{Symbol,String}(),
defaultColor::AbstractString="red",
autocolor_cb::Function=(histstep,csym,aniT)->(haskey(fsmColors, csym) ? fsmColors[csym] : defaultColor) ) where T
autocolor_cb::Function=(histstep,csym,aniT)->(haskey(fsmColors, csym) ? fsmColors[csym] : defaultColor) ) where {T, N}
#
# Dict{Symbol, Vector{Symbol}}
stateVisits = Dict{Symbol, Vector{Symbol}}()
Expand All @@ -433,6 +433,7 @@ function animateStateMachineHistoryIntervalCompound(hists::Dict{Symbol, Vector{T
prevList = Dict{Symbol, Vector{Int}}()
latestList = Dict{Symbol, Int}(whId => fsmStep)

prevT = aniT
frameCount = 0
# loop across time
@showprogress "exporting state machine images, $title " for stepCount in 1:totSteps
Expand All @@ -451,18 +452,20 @@ function animateStateMachineHistoryIntervalCompound(hists::Dict{Symbol, Vector{T
lbl = getStateLabel(hists[csym][lstep][3])
vertid = lookup[lbl]
vertColor=autocolor_cb(hists[csym][lstep], csym, aniT)
# vertColor = haskey(fsmColors,csym) ? fsmColors[csym] : defaultColor
setVisGraphOnState!(vg, vertid, appendxlabel=string(csym)*",", vertColor=vertColor )
easyn = haskey(easyNames, csym) ? easyNames[csym] : csym
setVisGraphOnState!(vg, vertid, appendxlabel="($easyn.$lstep),", vertColor=vertColor )
end

# and draw as many frames for that setup
for itr in 1:interval
# increment frame counter
frameCount += 1
deltaT = (aniT - prevT).value
prevT = aniT
# finally render one frame
renderStateMachineFrame(vg,
frameCount,
title=title,
title=title*" || dt=$deltaT ms ||",
show=false,
folderpath=folderpath,
timest=string(split(string(aniT),' ')[1]),
Expand Down

0 comments on commit a17903d

Please sign in to comment.