TrajectoryOptimization.jl minimal time problem

Maybe some of authors of the package are around here to answer the question. Is it possible to formulate minimal time trajectory optimization problem with TrajectoryOptimization.jl? How can I go about if I don’t know in advance the time trajectory might take? Maybe some other packages offering that capabilities can be suggested?

You can accomplish this with InfiniteOpt.jl: Minimum time manouevering problem + boundaries · Discussion #219 · pulsipher/InfiniteOpt.jl · GitHub

2 Likes

You can also use JuMP directly by modifying these examples:
https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/rocket_control/
https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/space_shuttle_reentry_trajectory/

I had modified these examples for time optimal control of Dubins vehicle. See if you find them useful.

# Dubins Car Time Optimal Control using JuMP
using JuMP
import Ipopt
import Plots

# Create JuMP model, using Ipopt as the solver
dubins = Model(Ipopt.Optimizer)
n = 100    # Time steps

# Dubins vehicle parameters
u_max = 0.3  # Maximum Angular Input

# Decision variables
@variables(dubins, begin
    Δt ≥ 0  # Time step
    # State variables
    x[1:n]           # x-coordinate
    y[1:n]           # y-coordinate
    θ[1:n]           # Orientation
    # Control variables
    -u_max ≤ u[1:n] ≤ u_max    # Thrust
end)

# Objective: Minimize time
@objective(dubins, Min, Δt)

# Initial conditions
@NLconstraint(dubins, x[1] == 0.0)
@NLconstraint(dubins, y[1] == 0.0)
@NLconstraint(dubins, θ[1] == 0.0)


# Constraints for satisfying Dynamics
for j in 2:n
    # x' = cos(θ)
    @NLconstraint(dubins, x[j] == x[j-1] + Δt * (cos(θ[j-1]) + cos(θ[j])) / 2)
    # y' = sin(θ)
    @NLconstraint(dubins, y[j] == y[j-1] + Δt * (sin(θ[j-1]) + sin(θ[j])) / 2)
    # θ' = u
    @NLconstraint(dubins, θ[j] == θ[j-1] + Δt * (u[j-1] + u[j]) / 2)
end

# Constraints for not passing through circles
rc = 1.0
xc = 5.0
yc = [5 + 0.5 * i for i = 1:5]
for i = 1:n
    @NLconstraint(dubins, (x[i] - xc)^2 + (y[i] - yc[1])^2 ≥ rc^2)
    @NLconstraint(dubins, (x[i] - xc)^2 + (y[i] - yc[2])^2 ≥ rc^2)
    @NLconstraint(dubins, (x[i] - xc)^2 + (y[i] - yc[3])^2 ≥ rc^2)
    @NLconstraint(dubins, (x[i] - xc)^2 + (y[i] - yc[4])^2 ≥ rc^2)
    @NLconstraint(dubins, (x[i] - xc)^2 + (y[i] - yc[5])^2 ≥ rc^2)
end


# Final time constraints
xf = 7.0
yf = 8.0
@NLconstraint(dubins, (x[n] - xf)^2 + (y[n] - yf)^2 ≤ 0.01)

# Solve for the control and state
println("Solving...")
optimize!(dubins)
# solution_summary(dubins)

# ## Display results

println("Time required: ", n * objective_value(dubins))
plt1 = Plots.plot(value.(x), value.(y), aspect_ratio = 1, legend = false, framestyle = :box)

# Circles
xt = zeros(n)
yt = zeros(n)
θt = LinRange(0, 2π, n)
for j = 1:5
	global plt1
    for i = 1:n
        xt[i] = xc + rc * cos(θt[i])
        yt[i] = yc[j] + rc * sin(θt[i])
    end
    Plots.plot!(plt1, xt, yt)
end

# Plotting final and initial locations
Plots.scatter!(plt1, [0, xf], [0, yf])
Plots.savefig(plt1, "dubins_obstacle.png")
display(fig1)
1 Like

I suppose it transcribe “infinite” parameters under the hood using some direct methods? So it does something similar to what @A_C suggested below hiding some machinery behind API?

I’ve tested many direct methods in JuMP like single/multiple shooting as well as orthogonal collocation / pseudospectral methods… TrajectoryOptimization.jl uses indirect methods and iterative solver. Not only it proved to be order of magnitude faster on my tasks. It is also more embedded systems friendly due to it’s iterative structure. So looking forward implementing something on real hardware in some C language I definitely would opt to something like TrajectoryOptimization.jl uses. But I can’t figure out how it is possible to formulate minimal time problems with it…

InfiniteOpt.jl transforms the model into a tractable representation. Currently, only direct methods are implemented (so yes something similar to the suggestion of @A_C), though it would be possible to add on indirect methods. With that said, it was not designed for use in high frequency control on embedded systems.