From 2ea63b44217f6ec022f919a3f435a209818f7e34 Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Thu, 15 Nov 2018 19:37:04 -0500 Subject: [PATCH] added PrettyPlots as a module --- REQUIRE | 5 +- src/NLOptControl.jl | 32 +- src/PrettyPlots/MPCPlots.jl | 95 ++++++ src/PrettyPlots/NLOptControl_plots.jl | 396 +++++++++++++++++++++++++ src/PrettyPlots/PrettyPlots.jl | 49 +++ src/PrettyPlots/PrettyUtils.jl | 72 +++++ src/PrettyPlots/old/compare_results.jl | 72 +++++ src/{ => old}/TODO.rst | 0 src/{ => old}/unused.jl | 0 9 files changed, 718 insertions(+), 3 deletions(-) create mode 100644 src/PrettyPlots/MPCPlots.jl create mode 100644 src/PrettyPlots/NLOptControl_plots.jl create mode 100644 src/PrettyPlots/PrettyPlots.jl create mode 100644 src/PrettyPlots/PrettyUtils.jl create mode 100644 src/PrettyPlots/old/compare_results.jl rename src/{ => old}/TODO.rst (100%) rename src/{ => old}/unused.jl (100%) diff --git a/REQUIRE b/REQUIRE index 4876e52..fe241a0 100644 --- a/REQUIRE +++ b/REQUIRE @@ -3,9 +3,12 @@ FastGaussQuadrature JuMP DataFrames 0.11 Ipopt -KNITRO +KNITRO 0.4 Interpolations MathProgBase CSV 0.2.4 OrdinaryDiffEq DiffEqBase +Colors +Plots +GR diff --git a/src/NLOptControl.jl b/src/NLOptControl.jl index 1a291ae..44a27dc 100644 --- a/src/NLOptControl.jl +++ b/src/NLOptControl.jl @@ -175,11 +175,14 @@ NLOpt( end # scripts -include("utils.jl"); +include("utils.jl") include("setup.jl"); include("ps.jl"); include("diffeq.jl") +include("PrettyPlots/PrettyPlots.jl") +using .PrettyPlots + export # Base functions TODO make a hamiltonian function evalConstraints!, @@ -246,5 +249,30 @@ export @NLconstraint, setvalue, getvalue, - setRHS + setRHS, + + # PrettyPlots + minDF, + maxDF, + plotSettings, + _pretty_defaults, + currentSettings, + + # NLOptControl plots + statePlot, + controlPlot, + costatesPlot, + costatesPlots, + allPlots, + adjust_axis, + + # MPC plots + mpcPlot, + tPlot, + optPlot, + + # Plots.jl exported functions + xlims!, + ylims!, + plot end # module diff --git a/src/PrettyPlots/MPCPlots.jl b/src/PrettyPlots/MPCPlots.jl new file mode 100644 index 0000000..dc30133 --- /dev/null +++ b/src/PrettyPlots/MPCPlots.jl @@ -0,0 +1,95 @@ +""" +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 04/26/2018 Last Modified: 04/26/2018 \n +--------------------------------------------------------------------------------------\n +""" +function mpcPlot(n,idx,kwargs...) + if !isdir(n.r.resultsDir); resultsDir!(n); end + stp = [statePlot(n,idx,st;kwargs...) for st in 1:n.ocp.state.num] + ctp = [controlPlot(n,idx,ctr;kwargs...) for ctr in 1:n.ocp.control.num] + + tp = tPlot(n,idx) + + if n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints + csp = [costatePlot(n,idx,st;kwargs...) for st in 1:n.ocp.state.num] + all = [stp;ctp;tp;csp] + else + all = [stp;ctp;tp] + end + + h = plot(all...,size=_pretty_defaults[:size]) + if !_pretty_defaults[:simulate]; savefig(string(n.r.resultsDir,"mpc.",_pretty_defaults[:format])) end + return h +end +""" +tp=tPlot(n,r,idx) +tp=tPlot(n,r,idx,tp;(:append=>true)) +# plot the optimization times +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 3/11/2017, Last Modified: 6/28/2017 \n +--------------------------------------------------------------------------------------\n +""" +function tPlot(n,idx::Int64,args...;kwargs...); + r = n.r.ocp + + kw = Dict(kwargs); + # check to see if user would like to add to an existing plot + if !haskey(kw,:append); append=false; + else; append = get(kw,:append,0); + end + if !append; tp=plot(0,leg=:false); else tp=args[1]; end + + if idx > length(r.dfsOpt[:tSolve]) + warn("Cannot plot idx = ", idx, " because length(r.dfsOpt[:tSolve]) = ", length(r.dfsOpt[:tSolve]), ". \n + reducing idx in tPlot!().") + idx = length(r.dfsOpt[:tSolve]) + end + + # check to see if user would like to label legend + if !haskey(kw,:legend);legend_string=""; + else; legend_string = get(kw,:legend,0); + end + + # to avoid a bunch of jumping around in the simulation + idx_max = length(r.dfsOpt[:tSolve]) + if (idx_max<10); idx_max=10 end + + if idx > 1 + scatter!(1:idx-1,r.dfsOpt[:tSolve][1:idx-1],marker=_pretty_defaults[:opt_marker][3],label=string(legend_string,"Previous Times")) + end + if isequal(r.dfsOpt[:status][idx],:Optimal) + scatter!((idx,r.dfsOpt[:tSolve][idx]),marker=_pretty_defaults[:opt_marker][1],label=string(legend_string,"Optimal")) + else + scatter!((idx,r.dfsOpt[:tSolve][idx]),marker=_pretty_defaults[:opt_marker][2],label=string(legend_string,string(r.dfsOpt[:status][idx])) ) + end + + plot!(1:length(r.dfsOpt[:tSolve]),n.mpc.v.tex*ones(length(r.dfsOpt[:tSolve])),line=_pretty_defaults[:limit_lines][2],leg=:true,label="real-time threshhold",leg=:topright) + + ylims!(0,max(n.mpc.v.tex*1.2, maximum(r.dfsOpt[:tSolve]))) + xlims!(1,length(r.dfsOpt[:tSolve])) + yaxis!("Optimization Time (s)") + xaxis!("Evaluation Number") + plot!(size=_pretty_defaults[:size]); + if !_pretty_defaults[:simulate] savefig(string(n.r.resultsDir,"tplot.",_pretty_defaults[:format])) end + + return tp +end + +""" +--------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 7/04/2017, Last Modified: 7/04/2017 \n +--------------------------------------------------------------------------------------\n +""" +function optPlot(n) + L = length(n.r.ocp.dfsOpt[:tSolve]) + temp = [n.r.ocp.dfsOpt[:objVal][jj] for jj in 1:L] + val = [idx for tempM in temp for idx=tempM] + opt = plot(1:L,val) + yaxis!("Objective Function Values") + xaxis!("Evaluation Number") + savefig(string(n.r.resultsDir,"optPlot.",_pretty_defaults[:format])) + return opt +end diff --git a/src/PrettyPlots/NLOptControl_plots.jl b/src/PrettyPlots/NLOptControl_plots.jl new file mode 100644 index 0000000..9ad87f5 --- /dev/null +++ b/src/PrettyPlots/NLOptControl_plots.jl @@ -0,0 +1,396 @@ +function adjust_axis(x_lim,y_lim) + + # scaling factors + al_x = [0.05, 0.05]; # x axis (low, high) + al_y = [0.05, 0.05]; # y axis (low, high) + + # additional axis movement + if x_lim[1]==0.0; a=-1; else a=0; end + if x_lim[2]==0.0; b=1; else b=0; end + if y_lim[1]==0.0; c=-1; else c=0; end + if y_lim[2]==0.0; d=1; else d=0; end + + xlim = Float64[0,0]; ylim = Float64[0,0]; + xlim[1] = x_lim[1]-abs(x_lim[1]*al_x[1])+a; + xlim[2] = x_lim[2]+abs(x_lim[2]*al_x[2])+b; + ylim[1] = y_lim[1]-abs(y_lim[1]*al_y[1])+c; + ylim[2] = y_lim[2]+abs(y_lim[2]*al_y[2])+d; + + xlims!((xlim[1],xlim[2])) + ylims!((ylim[1],ylim[2])) +end + + +""" +allPlots(n;idx=2) +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 2/10/2017, Last Modified: 11/10/2017 \n +--------------------------------------------------------------------------------------\n +""" +function allPlots(n;idx::Int64=1,kwargs...) + if !isdir(n.r.resultsDir); resultsDir!(n); end + stp = [statePlot(n,idx,st;kwargs...) for st in 1:n.ocp.state.num] + ctp = [controlPlot(n,idx,ctr;kwargs...) for ctr in 1:n.ocp.control.num] + + if n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints + csp = [costatePlot(n,idx,st;kwargs...) for st in 1:n.ocp.state.num] + all = [stp;ctp;csp] + else + all = [stp;ctp] + end + + h = plot(all...,size=_pretty_defaults[:size]) + if !_pretty_defaults[:simulate]; savefig(string(n.r.resultsDir,"main.",_pretty_defaults[:format])) end + return h +end + +""" +stp=statePlot(n,r.eval_num,7); +stp=statePlot(n,idx,st); +stp=statePlot(n,idx,st;(:legend=>"test1")); +stp=statePlot(n,idx,st,stp;(:append=>true)); +stp=statePlot(n,idx,st,stp;(:lims=>false)); +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 2/10/2017, Last Modified: 9/21/2017 \n +--------------------------------------------------------------------------------------\n +""" +function statePlot(n,idx::Int64,st::Int64,args...;kwargs...) + kw = Dict(kwargs); + + # check to see if user would like to add to an existing plot + if !haskey(kw,:append); append=false; + else; append = get(kw,:append,0); + end + if !append; stp=plot(0,leg=:false); else stp=args[1]; end + + # check to see if user would like to plot limits + if !haskey(kw,:lims); lims=true; + else; lims=get(kw,:lims,0); + end + + # check to see if user would like to label legend + if !haskey(kw,:legend); legend_string = ""; + else; legend_string = get(kw,:legend,0); + end + + # check length of n.r.ocp.dfs to see if there is data for the provided idx + if length(n.r.ocp.dfs) >= idx + ocpPlot = true + else + ocpPlot = false + end + + if ocpPlot + t_vec = linspace(0.0,n.r.ocp.dfs[end][:t][end],_pretty_defaults[:L]) + else + t_vec = linspace(0.0,n.r.ip.dfsplant[end][:t][end],_pretty_defaults[:L]) + end + + if lims + # plot the upper limits + if n.ocp.mXU[st]!=false + if !isnan(n.ocp.XU[st]);plot!(n.r.ocp.tst,n.ocp.XU_var[st,:],line=_pretty_defaults[:limit_lines][2],label=string(legend_string,"max"));end + else + if !isnan(n.ocp.XU[st]);plot!(t_vec,n.ocp.XU[st]*ones(_pretty_defaults[:L],1),line=_pretty_defaults[:limit_lines][2],label=string(legend_string,"max"));end + end + + # plot the lower limits + if n.ocp.mXL[st]!=false + if !isnan(n.ocp.XL[st]);plot!(n.r.ocp.tst,n.ocp.XL_var[st,:],line=_pretty_defaults[:limit_lines][1],label=string(legend_string,"min"));end + else + if !isnan(n.ocp.XL[st]);plot!(t_vec,n.ocp.XL[st]*ones(_pretty_defaults[:L],1),line=_pretty_defaults[:limit_lines][1],label=string(legend_string,"min"));end + end + end + + # plot the values TODO if there are no lims then you cannot really see the signal + if !_pretty_defaults[:plantOnly] && ocpPlot + if n.s.ocp.integrationMethod == :ps && _pretty_defaults[:polyPts] && isequal(n.r.ocp.dfsOpt[:status][idx],:Optimal) && !n.s.ocp.linearInterpolation && n.s.ocp.interpolationOn + int_color = 1 + for int in 1:n.ocp.Ni + if int_color > length(_pretty_defaults[:mpc_lines]) # reset colors + int_color = 1 + end + plot!(n.r.ocp.AlltpolyPts[idx][int],n.r.ocp.AllXpolyPts[idx][st][int],line=_pretty_defaults[:mpc_lines][int_color], label=string("poly. # ", int)) + int_color = int_color + 1 + end + scatter!((n.r.ocp.dfs[idx][:t],n.r.ocp.dfs[idx][n.ocp.state.name[st]]),marker=_pretty_defaults[:mpc_markers],label=string(legend_string,"colloc. pts.")) + else + plot!(n.r.ocp.dfs[idx][:t],n.r.ocp.dfs[idx][n.ocp.state.name[st]],marker=_pretty_defaults[:mpc_markers],line=_pretty_defaults[:mpc_lines][1],label=string(legend_string,"mpc")) + end + end + # MPC leads plant by an index + if _pretty_defaults[:plant] #&& idx!=1 + # values + temp = [n.r.ip.dfsplant[jj][n.ocp.state.name[st]] for jj in 1:idx]; + vals=[idx for tempM in temp for idx=tempM]; + + # time + temp = [n.r.ip.dfsplant[jj][:t] for jj in 1:idx]; + time=[idx for tempM in temp for idx=tempM]; + + plot!(time,vals,line=_pretty_defaults[:plant_lines][1],label=string(legend_string,"plant")); + end + if _pretty_defaults[:X0p] + X0 = n.r.ip.X0p[idx][1] + t = n.r.ip.X0p[idx][2] + scatter!((t,X0[st]),marker=_pretty_defaults[:X0p_marker],label="X0p") + end + adjust_axis(xlims(),ylims()); + xlims!(t_vec[1],t_vec[end]); + plot!(size=_pretty_defaults[:size]); + yaxis!(n.ocp.state.description[st]); xaxis!("time (s)"); + if !_pretty_defaults[:simulate]; savefig(string(n.r.resultsDir,n.ocp.state.name[st],".",_pretty_defaults[:format])); end + return stp +end + +""" +stp=statePlot(n,idx,st1,st2); +stp=statePlot(n,idx,st1,st2;(:legend=>"test1")); +stp=statePlot(n,idx,st1,st2,stp;(:append=>true),(:lims=>false)); +# to compare two different states +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 2/10/2017, Last Modified: 5/28/2017 \n +--------------------------------------------------------------------------------------\n +""" +function statePlot(n,idx::Int64,st1::Int64,st2::Int64,args...;kwargs...) + kw = Dict(kwargs); + + # check to see if user would like to add to an existing plot + if !haskey(kw,:append); kw_ = Dict(:append => false); append = get(kw_,:append,0); + else; append = get(kw,:append,0); + end + if !append; stp=plot(0,leg=:false); else stp=args[1]; end + + #if idx > length(n.r.ocp.dfs) + # warn("Cannot plot idx = ", idx, " because length(n.r.ocp.dfs) = ", length(n.r.ocp.dfs), ". \n + # Skipping idx in statePlot().") + # return stp + #end + + # check length of n.r.ocp.dfs to see if there is data for the provided idx + if length(n.r.ocp.dfs) >= idx + ocpPlot = true + else + ocpPlot = false + end + + # check to see if user would like to plot limits + if !haskey(kw,:lims); kw_ = Dict(:lims => true); lims = get(kw_,:lims,0); + else; lims = get(kw,:lims,0); + end + + # check to see if user would like to label legend + if !haskey(kw,:legend); kw_ = Dict(:legend => ""); legend_string = get(kw_,:legend,0); + else; legend_string = get(kw,:legend,0); + end + + # plot the limits + # TODO check if all constraints are given + # TODO make it work for linear varying stateTol + if lims + if !isnan(n.ocp.XU[st1]);plot!([n.ocp.XU[st1],n.ocp.XU[st1]],[n.ocp.XL[st2],n.ocp.XU[st2]],line=_pretty_defaults[:limit_lines][2],label=string(n.ocp.state.name[st1],"_max"));end + if !isnan(n.ocp.XL[st1]);plot!([n.ocp.XL[st1],n.ocp.XL[st1]],[n.ocp.XL[st2],n.ocp.XU[st2]],line=_pretty_defaults[:limit_lines][1],label=string(n.ocp.state.name[st1],"_min"));end + if !isnan(n.ocp.XU[st1]);plot!([n.ocp.XL[st1],n.ocp.XU[st1]],[n.ocp.XU[st2],n.ocp.XU[st2]],line=_pretty_defaults[:limit_lines][4],label=string(n.ocp.state.name[st2],"_max"));end + if !isnan(n.ocp.XL[st1]);plot!([n.ocp.XL[st1],n.ocp.XU[st1]],[n.ocp.XL[st2],n.ocp.XL[st2]],line=_pretty_defaults[:limit_lines][3],label=string(n.ocp.state.name[st2],"_min"));end + end + + # plot the values + if !_pretty_defaults[:plantOnly] && ocpPlot + plot!(n.r.ocp.dfs[idx][n.ocp.state.name[st1]],n.r.ocp.dfs[idx][n.ocp.state.name[st2]],line=_pretty_defaults[:mpc_lines][1],label=string(legend_string,"mpc")); + end + + if _pretty_defaults[:plant] #&& idx!=1 + # values + temp = [n.r.ip.dfsplant[jj][n.ocp.state.name[st1]] for jj in 1:idx] + vals1 = [idx for tempM in temp for idx=tempM] + + # values + temp = [n.r.ip.dfsplant[jj][n.ocp.state.name[st2]] for jj in 1:idx] + vals2 = [idx for tempM in temp for idx=tempM] + + plot!(vals1,vals2,line=_pretty_defaults[:plant_lines][1],label=string(legend_string,"plant")); + end + + adjust_axis(xlims(),ylims()) + plot!(size=_pretty_defaults[:size]) + xaxis!(n.ocp.state.description[st1]) + yaxis!(n.ocp.state.description[st2]) + if !_pretty_defaults[:simulate] savefig(string(n.r.resultsDir,n.ocp.state.name[st1],"_vs_",n.ocp.state.name[st2],".",_pretty_defaults[:format])); end + return stp +end + +""" +ctrp=controlPlot(n,idx,ctr); +ctrp=controlPlot(n,idx,ctr,ctrp;(:append=>true)); +# to plot control signals +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 2/10/2017, Last Modified: 9/19/2017 \n +--------------------------------------------------------------------------------------\n +""" +function controlPlot(n,idx::Int64,ctr::Int64,args...;kwargs...) + kw = Dict(kwargs); + + # check to see if user would like to add to an existing plot + if !haskey(kw,:append); kw_ = Dict(:append => false); append = get(kw_,:append,0); + else; append = get(kw,:append,0); + end + if !append; ctrp=plot(0,leg=:false); else ctrp=args[1]; end + + #if idx > length(n.r.ocp.dfs) + # warn("Cannot plot idx = ", idx, " because length(n.r.ocp.dfs) = ", length(n.r.ocp.dfs), ". \n + # Skipping idx in controlPlot().") + # return ctrp + #end + # check length of n.r.ocp.dfs to see if there is data for the provided idx + if length(n.r.ocp.dfs) >= idx + ocpPlot = true + else + ocpPlot = false + end + + # check to see if user would like to plot limits + if !haskey(kw,:lims); kw_ = Dict(:lims => true); lims = get(kw_,:lims,0); + else; lims = get(kw,:lims,0); + end + + # check to see if user would like to label legend + if !haskey(kw,:legend); kw_ = Dict(:legend => ""); legend_string = get(kw_,:legend,0); + else; legend_string = get(kw,:legend,0) + end + + if ocpPlot + t_vec = linspace(0.0,n.r.ocp.dfs[end][:t][end],_pretty_defaults[:L]) + else + t_vec = linspace(0.0,n.r.ip.dfsplant[end][:t][end],_pretty_defaults[:L]) + end + + # plot the limits + if lims + if !isnan(n.ocp.CU[ctr]);plot!(t_vec,n.ocp.CU[ctr]*ones(_pretty_defaults[:L],1),line=_pretty_defaults[:limit_lines][2],label="max");end + if !isnan(n.ocp.CL[ctr]); plot!(t_vec,n.ocp.CL[ctr]*ones(_pretty_defaults[:L],1),line=_pretty_defaults[:limit_lines][1],label="min"); end + end + + if !_pretty_defaults[:plantOnly] && ocpPlot + if n.s.ocp.integrationMethod == :ps && _pretty_defaults[:polyPts] && isequal(n.r.ocp.dfsOpt[:status][idx],:Optimal) && !n.s.ocp.linearInterpolation && n.s.ocp.interpolationOn + int_color = 1 + for int in 1:n.ocp.Ni + if int_color > length(_pretty_defaults[:mpc_lines]) # reset colors + int_color = 1 # reset colors + end + plot!(n.r.ocp.AlltpolyPts[idx][int],n.r.ocp.AllUpolyPts[idx][ctr][int],line=_pretty_defaults[:mpc_lines][int_color], label=string("poly. # ", int)) + int_color = int_color + 1 + end + scatter!(n.r.ocp.dfs[idx][:t],n.r.ocp.dfs[idx][n.ocp.control.name[ctr]],marker=_pretty_defaults[:mpc_markers],label=string(legend_string,"colloc. pts.")) + else + plot!(n.r.ocp.dfs[idx][:t],n.r.ocp.dfs[idx][n.ocp.control.name[ctr]],marker=_pretty_defaults[:mpc_markers],line=_pretty_defaults[:mpc_lines][1],label=string(legend_string,"mpc")) + end + end + + if _pretty_defaults[:plant] #&& idx!=1 + # values + temp = [n.r.ip.dfsplant[jj][n.ocp.control.name[ctr]] for jj in 1:idx] + vals = [idx for tempM in temp for idx=tempM]; + + # time + temp = [n.r.ip.dfsplant[jj][:t] for jj in 1:idx] + time = [idx for tempM in temp for idx=tempM] + + plot!(time,vals,line=_pretty_defaults[:plant_lines][1],label=string(legend_string,"plant")); + end + adjust_axis(xlims(),ylims()); + xlims!(t_vec[1],t_vec[end]); + plot!(size=_pretty_defaults[:size]); + yaxis!(n.ocp.control.description[ctr]); xaxis!("time (s)"); + if !_pretty_defaults[:simulate] savefig(string(n.r.resultsDir,n.ocp.control.name[ctr],".",_pretty_defaults[:format])) end + return ctrp +end + + + + +""" +costatesPlot(n) +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 11/10/2017, Last Modified: 11/10/2017 \n +--------------------------------------------------------------------------------------\n +""" +function costatesPlot(n;idx::Int64=1,kwargs...) + if !(n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints) + error(" if n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints \n + must all be true.") + end + + if !isdir(n.r.resultsDir); resultsDir!(n); end + + csp = [costatePlot(n,idx,st;kwargs...) for st in 1:n.ocp.state.num]; + h = plot(csp...,size=_pretty_defaults[:size]) + if !_pretty_defaults[:simulate]; savefig(string(n.r.resultsDir,"cs_main.",_pretty_defaults[:format])) end + return h +end + +""" +costatePlot(n,idx,st) +--------------------------------------------------------------------------------------\n +Author: Huckleberry Febbo, Graduate Student, University of Michigan +Date Create: 11/10/2017, Last Modified: 11/10/2017 \n +--------------------------------------------------------------------------------------\n +""" +function costatePlot(n,idx::Int64,st::Int64;kwargs...) + if !(n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints) + error(" if n.s.ocp.evalCostates && n.s.ocp.integrationMethod == :ps && n.s.ocp.evalConstraints \n + must all be true.") + end + kw = Dict(kwargs); + + # check to see if user would like to add to an existing plot + if !haskey(kw,:append); append=false; + else; append = get(kw,:append,0); + end + if !append; csp=plot(0,leg=:false); else csp=args[1]; end + + if length(n.r.ocp.dfs) >= idx + ocpPlot = true + else + ocpPlot = false + end + + # check to see if user would like to label legend + if !haskey(kw,:legend); legend_string = ""; + else; legend_string = get(kw,:legend,0); + end + + if ocpPlot + t_vec=linspace(0.0,n.r.ocp.dfs[end][:t][end],_pretty_defaults[:L]); + else + t_vec=linspace(0.0,n.r.ip.dfsplant[end][:t][end],_pretty_defaults[:L]); + end + + if n.s.ocp.integrationMethod == :ps + t_st_int = [n.r.ocp.tst[n.ocp.Nck_cum[int]+1:n.ocp.Nck_cum[int+1]+1] for int in 1:n.ocp.Ni] # this is redundant in interpolateLagrange!() + + int_color = 1 + for int in 1:n.ocp.Ni + if int_color > length(_pretty_defaults[:mpc_lines]) # reset colors + int_color = 1 + end + plot!(n.r.ocp.AlltpolyPts[idx][int],n.r.ocp.AllCSpolyPts[idx][st][int],line=_pretty_defaults[:mpc_lines][int_color], label=string("poly. # ", int)) + int_color = int_color + 1 + scatter!(t_st_int[int][1:end-1],n.r.ocp.CS[st][int],marker=_pretty_defaults[:mpc_markers],label=string(legend_string,"costate pts.")) + end + #else # NOTE for now :tm methods do not have a costate option + # plot!(n.r.ocp.dfs[idx][:t],n.r.ocp.CS[st],marker=_pretty_defaults[:mpc_markers],line=_pretty_defaults[:mpc_lines][1],label=string(legend_string,"mpc")) + end + + adjust_axis(xlims(),ylims()); + xlims!(t_vec[1],t_vec[end]); + plot!(size=_pretty_defaults[:size]); + yaxis!(string(n.ocp.state.description[st]," costate")); xaxis!("time (s)"); + + if !_pretty_defaults[:simulate]; savefig(string(n.r.resultsDir,n.ocp.state.name[st]," costate.",_pretty_defaults[:format])); end + return csp +end diff --git a/src/PrettyPlots/PrettyPlots.jl b/src/PrettyPlots/PrettyPlots.jl new file mode 100644 index 0000000..50d1187 --- /dev/null +++ b/src/PrettyPlots/PrettyPlots.jl @@ -0,0 +1,49 @@ +module PrettyPlots + +using Colors +using DataFrames +using Plots +#import Plots.gr +#import Plots.pyplot +import Plots.xlims!, Plots.ylims!, Plots.plot +gr(); # default backend +#pyplot() +#using VehicleModels # need for parameters +#using NLOptControl # need for resultsDir!() + +include("PrettyUtils.jl") +include("NLOptControl_plots.jl") +include("MPCPlots.jl") +#include("VehicleModels_plots.jl") + +export + # PrettyUtils.jl + minDF, + maxDF, + plotSettings, + _pretty_defaults, + currentSettings, + + # NLOptControl.jl plots + statePlot, + controlPlot, + costatesPlot, + costatesPlots, + allPlots, + adjust_axis, + + # MPC plots + mpcPlot, + tPlot, + optPlot, + + # Plots.jl exported functions + xlims!, + ylims!, + plot + #Plots.gui(), + #Plots.pyplot(), + #Plots.gr(), + #Plots.pgfplots() + +end # module diff --git a/src/PrettyPlots/PrettyUtils.jl b/src/PrettyPlots/PrettyUtils.jl new file mode 100644 index 0000000..cd5e472 --- /dev/null +++ b/src/PrettyPlots/PrettyUtils.jl @@ -0,0 +1,72 @@ +#lc=distinguishable_colors(10); +const _pretty_defaults = Dict( + :size =>(700,700), # size of figure + :format =>"png", # format for output plots + :plant =>false, # bool for simulation of plant as well as MPC + :X0p =>false, # bool for simulation of X0p + :X0p_marker =>(:circle,:red,5.0,1.0), + :plantOnly =>false, # bool for plotting only the plant response + :polyPts =>true, # bool for plotting the individual polynomials + :simulate =>false, # bool for simulation + :L =>100, # format for output plots + :mpc_lines =>[(2.7,:blue,:solid),(2.7,:red,:solid),(2.7,:darkgreen,:solid), + (2.7,:yellow,:solid),(2.7,:black,:solid),(2.7,:firebrick,:solid), + (2.7,:gold,:solid),(2.7,:greenyellow,:solid),(2.7,:hotpink,:solid), + (2.7,:steelblue,:solid),(2.7,:aqua,:solid),(2.7,:teal,:solid), + (2.7,:blue,:dash),(2.7,:red,:dash),(2.7,:darkgreen,:dash), + (2.7,:yellow,:dash),(2.7,:black,:dash),(2.7,:firebrick,:dash), + (2.7,:gold,:dash),(2.7,:greenyellow,:dash),(2.7,:hotpink,:dash), + (2.7,:steelblue,:dash),(2.7,:aqua,:dash),(2.7,:teal,:dash)], + :mpc_markers =>(:circle,:blueviolet,0.0,1.0), + :plant_lines =>[(4.3,:darkgreen,:solid),(4.3,:darkgreen,:dash),(4.3,:black,:solid),(4.3,:black,:dash)], + :limit_lines =>[(2.0,:deeppink1,:solid),(2.0,:deeppink1,:dash),(2.0,:blueviolet,:solid),(2.0,:blueviolet,:dash)], + :opt_marker => [(:circle,:green,3.0),(:rect,:red,3.0),(:circle,:black,3.0)], + + # for VehicleModel.jl + :vehicle_marker =>(:black,:rect,5.0,1.0), + :vehicle_fill =>(0,1,:black), + :goal_marker =>[(:circle,:springgreen,10.0,1.0),(:circle,:green,10.0,1.0)], + :goal_fill =>[(0,1,:springgreen),(0,1,:green)], + :goal_line =>(1.0,0.0,:solid,:green), + :obstacle_marker =>(:circle,:red,10.0,1.0), + :obstacle_fill =>(0,1.0,:red), + :obstacle_line =>(1.0,0.0,:solid,:red), + :tire_force_lims =>(0,12000), + :ax_lims =>(-5,2), + :vehicle_width =>1.9, + :vehicle_length =>3.3, + :lidar_line =>(1.0,0.0,:solid,:red), + :lidar_fill =>(0,0.2,:yellow), +) + +""" +plotSettings(;(:simulate=>true)) +plotSettings(;(:mpc_lines =>[(4.0,:blueviolet,:solid),(4.0,:blueviolet,:dash)]), + (:plant_lines =>[(3.0,:darkgreen,:solid),(3.0,:darkgreen,:solid)]), + (:limit_lines =>[(2.0,:turquoise,:solid),(2.0,:violet,:solid),(2.0,:orchid,:solid),(2.0,:darksalmon,:solid)]), + (:size=>(1000,1000)) + ) +plotSettings(;(:obstacle_marker =>(:circle,:red,10.0,1.0)), + (:goal_marker=>(:circle,:green,10.0,1.0)) + ) + plotSettings(;(:mpc_lines =>[(4.0,:blueviolet,:solid)]),(:size=>(700,700))) +# this function can be called to modify the default settings in PrettyPlots.jl +# check out Colors.jl for an incredible amount of colors! +""" +function plotSettings(;kwargs...) + kw = Dict(kwargs); + for (key,value) in kw + if haskey(_pretty_defaults,key) + _pretty_defaults[key]=value + else + error("Unknown key: ", kw) + end + end +end +""" +currentSettings() +# show the current plot settings +""" +function currentSettings() + _pretty_defaults +end diff --git a/src/PrettyPlots/old/compare_results.jl b/src/PrettyPlots/old/compare_results.jl new file mode 100644 index 0000000..7f64c61 --- /dev/null +++ b/src/PrettyPlots/old/compare_results.jl @@ -0,0 +1,72 @@ +using DataFrames +using Plots +using ImplicitEquations +using VehicleModels + +# Set The Problem Up +main_dir="/home/febbo/Documents/workspace/OCP" +results_name = "testing_clp76"; # Name Folder to Store Comparison Results in +results_dir = string(main_dir,"/results/",results_name) +warn("you may have the wrong senario!") +senario = "s1.jl" #TODO save this with the actual test data! + +# define vehicle parameters; has constraints on vehicle model for optimization +pa = Vpara(); # initialize parameter set +@unpack_Vpara pa # unpack parameters + +include(string(main_dir,"/initialize.jl")) + + +# Choose Results to Compare +k = 4 # number of results to compare +path = ["","","",""] # should match k +path[1] = "/home/febbo/Documents/workspace/OCP/results/testing_clp76eulerIPOPT"; +path[2] = "/home/febbo/Documents/workspace/OCP/results/testing_clp76trap2IPOPT"; +path[3] = "/home/febbo/Documents/workspace/OCP/results/testing_clp76eulerKNITRO"; +path[4] = "/home/febbo/Documents/workspace/OCP/results/testing_clp76KNITRO"; + +# Plot Settings +label_string = ["Euler & IPOPT", "Trap. & IPOPT","Euler & KNITRO", "Trap. & KNITRO"]; + +if isdir(results_dir) + rm(results_dir; recursive=true) + print("\n The old results have all been deleted! \n \n") +end + +dfs=data_sets(k,"STATES") # put the data from each test into a DataFrame +dfs_opt=data_sets(k,"OPT_info") +mkdir(results_dir) +cd(results_dir) + +sa=saplot(dfs,label_string,false,pa) +sr=srplot(dfs,label_string,false,pa) +yaw=yawplot(dfs,label_string,false,pa) +yawr=yawrplot(dfs,label_string,false,pa) + +longv=longvplot(dfs,label_string,false,pa) +ax=axplot(dfs,label_string,false,pa) +jx=jxplot(dfs,label_string,false,pa) + +latv=latvplot(dfs,label_string,false,pa) + +pp=pplot(dfs,1,label_string,false,false,obs_data,s_data,pa) + +lt=ltplot(dfs,label_string,false,pa) +vt=vtplot(dfs,label_string,false,pa) + +# make a figure with all states and controls +plot(longv, ax, jx, sa, sr, yaw, yawr, latv, pp, size=(1800,1200)) +savefig("main.png") + +# make a figure with the tire forces +plot(lt, vt, size=(1800,1200),layout = grid(2,1) ) +savefig("tire_f.png") + +# make a simulation with all vehicles +#panim_fun(label_string) + +optplot(dfs_opt,label_string,false) + +tplot(dfs_opt,dfs,label_string,false) + +cd(main_dir) diff --git a/src/TODO.rst b/src/old/TODO.rst similarity index 100% rename from src/TODO.rst rename to src/old/TODO.rst diff --git a/src/unused.jl b/src/old/unused.jl similarity index 100% rename from src/unused.jl rename to src/old/unused.jl