# include("../src/DirectOptimalControl.jl")
# import .DirectOptimalControl as DOC

import DirectOptimalControl as DOC
import Ipopt
using JuMP

Common parameters

vm = 1.0   # Max forward speed
um = 1.0   # Max turning speed
ns = 3     # Number of states
nu = 2     # Number of inputs
n = 20    # Time steps

System dynamics

function dyn(x, u, t, p)
    return [u[2] * cos(x[3]), u[2] * sin(x[3]), u[1]]
end

Objective Function Running cost

function L(x, u, t, p)
    return 1.0
end

function phi(xf, uf, tf, p)
    return 0.0
end

function integralfun(x, u, t, p)
    return nothing
end

function pathfun(x, u, t, p)
    return nothing
end

OC = DOC.OCP()
OC.tol = 1e-5
OC.mesh_iter_max = 15
OC.objective_sense = "Min"
set_optimizer(OC.model, Ipopt.Optimizer)
set_attribute(OC.model, "linear_solver", "mumps")
set_attribute(OC.model, "print_level", 0)
# set_attribute(OC.model, "max_iter", 500)
set_attribute(OC.model, "tol", 1e-6)

Phase 1

ph1 = DOC.PH(OC)
ph1.L = L
ph1.phi = phi
ph1.dyn = dyn
ph1.integralfun = integralfun
ph1.collocation_method = "hermite-simpson"
ph1.scale_flag = true

ph1.n = n
ph1.ns = ns
ph1.nu = nu
ph1.nq = 0
ph1.nk = 0

Auxillary parameters

ph1.p = (k1 = 1.0, k2 = 2.0)

ph1.limits.ll.u = [-1.0, 0.75*vm]
ph1.limits.ul.u = [1.0, vm]
ph1.limits.ll.x = [-10.0, -10.0, -10.0]
ph1.limits.ul.x = [10.0, 10.0, 10.0]
ph1.limits.ll.xf = [5.0, 5.0, π / 2 + π / 4]
ph1.limits.ul.xf = [5.0, 5.0, π / 2 + π / 4]
ph1.limits.ll.xi = [0, 0, -π / 2]
ph1.limits.ul.xi = [0, 0, -π / 2]
ph1.limits.ll.ti = 0.0
ph1.limits.ul.ti = 0.0
ph1.limits.ll.tf = 5.0
ph1.limits.ul.tf = 20.0
ph1.limits.ll.dt = 5.0
ph1.limits.ul.dt = 20.0
ph1.limits.ll.k = []
ph1.limits.ul.k = []

ph.setinitialvalues can take two values: "Auto" and "User" Set initial values

ph1.set_initial_vals = "Auto"

Phase 2

ph2 = DOC.PH(OC)
ph2.L = L
ph2.phi = phi
ph2.dyn = dyn
ph2.integralfun = integralfun
ph2.collocation_method = "hermite-simpson"
ph2.scale_flag = true

ph2.n = n
ph2.ns = ns
ph2.nu = nu
ph2.nq = 0
ph2.nk = 0

ph2.p = (k1 = 1.0, k2 = 2.0)

ph2.limits.ll.u = [-1.0, 0.75*vm]
ph2.limits.ul.u = [1.0, vm]
ph2.limits.ll.x = [-10.0, -10.0, -10.0]
ph2.limits.ul.x = [10.0, 10.0, 10.0]
ph2.limits.ll.xf =  [-5, 5, 0.0]
ph2.limits.ul.xf =  [-5, 5, 0.0]
ph2.limits.ll.xi = ph1.limits.ll.xf
ph2.limits.ul.xi = ph1.limits.ul.xf
ph2.limits.ll.ti = ph1.limits.ll.tf
ph2.limits.ul.ti = ph1.limits.ul.tf
ph2.limits.ll.dt = 5.0
ph2.limits.ul.dt = 20.0
ph2.limits.ll.tf = ph2.limits.ll.ti + ph2.limits.ll.dt
ph2.limits.ul.tf = ph2.limits.ul.ti + ph2.limits.ul.dt

Phase 3

ph3 = DOC.PH(OC)
ph3.L = L
ph3.phi = phi
ph3.dyn = dyn
ph3.integralfun = integralfun

ph3.n = n
ph3.tau = range(start = 0, stop = 1, length = ph3.n)
ph3.ns = ns
ph3.nu = nu
ph3.p = (k1 = 1.0, k2 = 2.0)

ph3.limits.ll.u = [-1.0, 0.75*vm]
ph3.limits.ul.u = [1.0, vm]
ph3.limits.ll.x = [-10.0, -10.0, -10.0]
ph3.limits.ul.x = [10.0, 10.0, 10.0]
ph3.limits.ll.xf =  [-5, -5, 0.0]
ph3.limits.ul.xf =  [-5, -5, 0.0]
ph3.limits.ll.xi = ph2.limits.ll.xf
ph3.limits.ul.xi = ph2.limits.ul.xf
ph3.limits.ll.ti = ph2.limits.ll.tf
ph3.limits.ul.ti = ph2.limits.ul.tf
ph3.limits.ll.dt = 7.0
ph3.limits.ul.dt = 20.0
ph3.limits.ll.tf = ph3.limits.ll.ti + ph3.limits.ll.dt
ph3.limits.ul.tf = ph3.limits.ul.ti + ph3.limits.ul.dt
ph3.collocation_method = "hermite-simpson"
ph3.scale_flag = true

Phase 4

ph4 = DOC.PH(OC)
ph4.L = L
ph4.phi = phi
ph4.dyn = dyn
ph4.integralfun = integralfun

ph4.n = n
ph4.tau = range(start = 0, stop = 1, length = ph4.n)
ph4.ns = ns
ph4.nu = nu
ph4.p = (k1 = 1.0, k2 = 2.0)

ph4.limits.ll.u = [-1.0, 0.75*vm]
ph4.limits.ul.u = [1.0, vm]
ph4.limits.ll.x = [-10.0, -10.0, -10.0]
ph4.limits.ul.x = [10.0, 10.0, 10.0]
ph4.limits.ll.xf =  ph1.limits.ll.xi
ph4.limits.ul.xf =  ph1.limits.ul.xi
ph4.limits.ll.xi = ph3.limits.ll.xf
ph4.limits.ul.xi = ph3.limits.ul.xf
ph4.limits.ll.ti = ph3.limits.ll.tf
ph4.limits.ul.ti = ph3.limits.ul.tf
ph4.limits.ll.dt = 7.0
ph4.limits.ul.dt = 20.0
ph4.limits.ll.tf = ph4.limits.ll.ti + ph4.limits.ll.dt
ph4.limits.ul.tf = ph4.limits.ul.ti + ph4.limits.ul.dt
ph4.collocation_method = "hermite-simpson"
ph4.scale_flag = true

Add the boundary constraints

function psi(ocp::DOC.OCP)
    (;ph) = ocp

    v4 = ph[2].ti - ph[1].tf
    v7 = ph[3].ti - ph[2].tf
    v10 = ph[4].ti - ph[3].tf

    return [v4, v7, v10]
end

OC.psi = psi
OC.npsi = 3
OC.set_obj_lim = true
OC.obj_llim = 0.0
OC.obj_ulim = 43
OC.psi_llim = [0.0, 0.0, 0.0]
OC.psi_ulim = [0.0, 0.0, 0.0]

DOC.setup_mpocp(OC)
DOC.solve_mpocp(OC)
# DOC.solve(OC)

Solve for the control and state

solution_summary(OC.model)

Display results

println("Min time: ", objective_value(OC.model))


# using GLMakie
# f1, ax1, l1 = lines(value.(ph1.x[1, :]), value.(ph1.x[2, :]))
# l2 = lines!(ax1, value.(ph2.x[1, :]), value.(ph2.x[2, :]))
# l3 = lines!(ax1, value.(ph3.x[1, :]), value.(ph3.x[2, :]))
# l4 = lines!(ax1, value.(ph4.x[1, :]), value.(ph4.x[2, :]))
# ax1.autolimitaspect = 1.0
# # f1

# f2, ax2, l21 = lines(value.(ph1.t), value.(ph1.u[1, :]))
# l22 = lines!(ax2, value.(ph2.t), value.(ph2.u[1, :]))
# l23 = lines!(ax2, value.(ph3.t), value.(ph3.u[1, :]))
# l24 = lines!(ax2, value.(ph4.t), value.(ph4.u[1, :]))
# f2

# f3, ax3, l31 = lines(value.(ph1.t), value.(ph1.u[2, :]))
# l32 = lines!(ax3, value.(ph2.t), value.(ph2.u[2, :]))
# l33 = lines!(ax3, value.(ph3.t), value.(ph3.u[2, :]))
# l34 = lines!(ax3, value.(ph4.t), value.(ph4.u[2, :]))
# f3


# f4, ax4, l4 = lines(value.(ph1.xinit[1, :]), value.(ph1.xinit[2, :]))
# l2 = lines!(ax4, value.(ph2.xinit[1, :]), value.(ph2.xinit[2, :]))
# l3 = lines!(ax4, value.(ph3.xinit[1, :]), value.(ph3.xinit[2, :]))
# l4 = lines!(ax4, value.(ph4.xinit[1, :]), value.(ph4.xinit[2, :]))
# ax4.autolimitaspect = 1.0
# f4

This page was generated using Literate.jl.