Hi! I was actually able to get this working wtih help from @araujoms on slack, but documenting here for future Googlers.
I am trying to model a slider-crank mechanism like this:
I want to minimize the height of the system for a certain amount of travel of the slider box.
Here is my original (incorrect!!) code:
using JuMP, Ipopt
model = Model(Ipopt.Optimizer)
# length of crank shaft off the motor shaft
@variable(model, r_crank >= 0, start = 3)
# length of arm from end of crank to connection point on slider block
@variable(model, r_arm >= 0, start = 8)
# Clearance from lowest point of crank shaft to the line of action for the slider block
@variable(model, 8 >= clearance >= 7, start = 7.5)
# total offset between line of action and motor shaft
offset = r_crank + clearance
# angle formed by the line perpendicular to the line of action which intersects the motor shaft and the arm when it is fully retracted
θ = acos(offset/r_arm)
x = cos(θ)*r_crank
z = sin(θ)*r_crank
y = x - offset
a = √(r_arm^2 - y^2)
# minimum x-dimension distance from motor shaft to the connection point on the slider block
d_min = sin(θ)*r_arm
# max x-dimension distance from motor shaft to the connection point on the slider block
d_max = z + a
#total distance traveled by slider box
d_diff = d_max - d_min
# we want the slider box to move 15 to 20 cm
@constraint(model, c1, 15 <= d_diff <= 20)
# we want the minimum angle to be at least 45 and at most 90 degrees
@constraint(model, c2, 45*π/180 <= θ <= 90*π/180)
# we'd like the system to be as short as possible
@objective(model, Min, offset)
# We'd like the arm to be as short as possible
@objective(model, Min, r_arm+r_crank)
optimize!(model)
This was throwing the error:
This is Ipopt version 3.14.16, running with linear solver MUMPS 5.7.3.
Number of nonzeros in equality constraint Jacobian...: 0
Number of nonzeros in inequality constraint Jacobian.: 8
Number of nonzeros in Lagrangian Hessian.............: 12
The inequality constraints contain an invalid number
Number of Iterations....: 0
Number of objective function evaluations = 0
Number of objective gradient evaluations = 0
Number of equality constraint evaluations = 0
Number of inequality constraint evaluations = 1
Number of equality constraint Jacobian evaluations = 0
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 0
Total seconds in IPOPT = 0.000
EXIT: Invalid number in NLP function or derivative detected.
This code had the following problems:
y
could be greater thanr_arm
soa
could be imaginaryYou need to useI was corrected below@NLconstraint
for constraints that have nonlinear functions.- I didn’t have a constraint to relate the length of the arm to the length of the crank, so I was getting ridiculous results even after the errors were fixed.
- I want to be able to pick how much clearance I have with my offset and how far the slider box travels, so that shouldn’t be a variable but a constant input.
In the end, I got this as my final code:
using JuMP, Ipopt
const clearance = 7
const target_distance_traveled = 20
begin
model = Model(Ipopt.Optimizer)
register(model, :√, 1, √; autodiff = true)
# length of crank shaft off the motor shaft
@variable(model, r_crank >= 0, start = 3)
# length of arm from end of crank to connection point on slider block
@variable(model, r_arm >= 0, start = 5*clearance)
# angle between the vertical line connecting the motor shaft to the line of action and the arm when in the retracted position
@variable(model, 50*π/180<= θ <= 85*π/180, start = 65*π/180)
# total offset between line of action and motor shaft
offset = r_crank + clearance
# y-dimesion distance from motor shaft
x = cos(θ)*r_crank
z = sin(θ)*r_crank
y = offset - x
a = √(r_arm^2 - y^2)
# minimum x-dimension distance from motor shaft to the connection point on the slider block
d_min = sin(θ)*r_arm
# max x-dimension distance from motor shaft to the connection point on the slider block
d_max = z + a
#total distance traveled by slider box
d_diff = d_max - d_min
@NLconstraint(model, d_diff == target_distance_traveled)
# need to assert that the arm is longer than the height above the line of action when extended or we get NaN results.
@NLconstraint(model, r_arm >= y)
# Need to assert the relationship between the arm and crank length
@NLconstraint(model, r_arm == 2r_crank + √(y^2+(d_min-z)^2))
# we'd like the system to be as short as possible
@objective(model, Min, offset)
optimize!(model)
end
After these modifications, I’m getting reasonable results and no errors
I’m just a hobbyist here with no training in mechanical engineering, optimization, or anything else, so I just want to say what a pleasure the JuMP.jl docs are and how helpful this community is. Thank you @jd-foster, @araujoms , and @odow .