Hello,
I’m new to JuMP and trying to implement a yaw-plane vehicle model. The inputs to the function are arrays of the steering and throttle inputs (for every discrete time step). The model runs fine on its own, but adding JuMP has introduced dual numbers. It appears as though every time I try allowing the Dual type to propagate throughout my function, it still tries to cast it as a Float64 value. As I understand, this is a relatively common issue with JuMP newbies.
My question: how can I pass the steering angles and throttle inputs to my function without casting them as Float64?
Code:
#From what I've found online, it helps to define the arguments as a splat of #type Real
function opt_function(control::Type...) where {Type :< Real}
#INITIAL PARAMETERS
x0 = 0 #metres
y0 = -3 #metres
theta0 = 0 #rad
u0 = 20 #m/s
v0 = 0 #m/s
r0 = 0 #m/s
X0 = [x0, y0, theta0, u0, v0, r0]
########################################
#PROBLEM SECTION
#Trying to store the dual number values passed in the control array in "slip" and "steer"
slip = Vector{Type}(undef, Int(ceil(T/delT)))
steer = Vector{Type}(undef, Int(ceil(T/delT)))
#Control[] is formatted as a vcat(slip, steer)
for i in 1:Int(ceil(length(control)/2))
slip[i] = control[i]
steer[i] = control[i+Int(length(control)/2)]
end
#########################################
#vehicle parameters
m = 1914 #kg
Izz = 2600 #kg*m^2
a = 1.35 #metres
b = 1.5 #metres
kx = 100000 #N/m
cf = 80000#2*1437*dpr #N/m
cr = 80000#2*1507*dpr #N/m
params = [m, Izz, a, b, kx, cf, cr]
#Calls the vehicle model
return bicycle_discrete_opt([slip,steer], X0, params, T, delT)
end
###############################################
#Leaving this in case it helps
using JuMP
using Ipopt
global T = 5 # end time {seconds}
global delT = 2.5 #time step {seconds}
model = Model(Ipopt.Optimizer)
#X = x (global), y (global), theta, u ,v ,r (1x6 vector)
#@variable(model, slip_coeffs[1:3])
#@variable(model, steer_coeffs[1:3])
#@variable(model, slip[1:Int(ceil(T/delT))])
#@variable(model, steer[1:Int(ceil(T/delT))])
@variable(model, control[1:2*Int(ceil(T/delT))])
@operator(model, bicycle_op, 2, (control...) -> opt_function(collect(control)))
@objective(model, Min, bicycle(control...))
#optimize!(model)
#############################################
#yaw-plane model, I hope this formats better than it shows in this window
function bicycle_discrete_opt(slip, steer, x0, p, T, delT)
m, Izz, a, b, kx, cf, cr = p
x = Array{Real, 2}(undef, Int(ceil(T/delT))+1, 6)
x[1,:] .= x0
for i in 1:Int(ceil(T/delT))
t = (i-1)*delT
x[i+1,1] = x[i,1] + (x[i,4]*cos(x[i,3])-x[i,5]*sin(x[i,3]))*delT #x_dot (global coordinate frame) #Note the negative sign (x aligns with initial vehicle dir, y is left positive)
x[i+1,2] = x[i,2] + (x[i,4]*sin(x[i,3])+x[i,5]*cos(x[i,3]))*delT #y_dot (global coordinate frame)
x[i+1,3] = x[i,3] + (x[i,6]*pi/180)*delT #theta_dot (radians)
x[i+1,4] = x[i,4] + (2*kx*slip_ratio[i]/m)*delT #u_dot
x[i+1,5] = x[i,5] + ((cf*steer[i] - (x[i,5]*(cf+cr) + (x[i,6]*pi/180)*(a*cf - b*cr + m*x[i,4]^2))/x[i,4])/m)*delT #v_dot
x[i+1,6] = x[i,6] + ((180/pi)*(cf*a*steer[i] - (x[i,5]*(a*cf - b*cr) +(x[i,6]*pi/180)*(a^2 * cf + b^2 *cr))/x[i,4])/Izz)*delT #r_dot (deg/s)
end