For some reason, adding a ForceSensor from ModelingToolkitStandardLibrary breaks the following model.
using ModelingToolkit
import ModelingToolkit: connect, t_nounits as t, D_nounits as D
using ModelingToolkitStandardLibrary
using DifferentialEquations
@named mass = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Mass(m=1)
@named spring = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Spring(k=1)
@named fix = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Fixed()
@named force = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Force()
@named fsensor = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.ForceSensor()
eqs = Equation[
connect(mass.flange, spring.flange_b)
connect(fix.flange, spring.flange_a)
]
@named model = ODESystem(eqs, t; systems=[mass, spring, fix])
sys = mtkcompile(model)
initial = Dict{Num,Any}([
mass.s => 1.
mass.v => 0.
]
)
prob = ODEProblem(sys, initial, (0.0, 100.0)) # Works
sol_mass_nosens = solve(prob, Rodas5())
eqs = Equation[
connect(mass.flange, spring.flange_b)
connect(fix.flange, spring.flange_a)
connect(fix.flange, fsensor.flange_a)
connect(fsensor.flange_b, mass.flange)
]
@named model = ODESystem(eqs, t; systems=[mass, spring, fix, fsensor])
sys = mtkcompile(model)
initial = Dict{Num,Any}([
mass.s => 1.
mass.v => 0.
]
)
prob = ODEProblem(sys, initial, (0.0, 100.0)) # Fails on initialization or returns nothing depending on initial_positions
sol_mass_sens = solve(prob, Rodas5())
I figured adding a sensor should only add some “slave” equations but not over constrain the system. Is this a bug in the ModelingToolkitStandardLibrary or am I missing something ?
What is the error or warning?
It’s a warning, stating that the system is overdetermined. So I’m guessing that the sensor enforces some variable (probably through its Flanges). But it leads to an empty solution.
┌ Warning: Initialization system is overdetermined. 2 equations for 0 unknowns. Initialization will default to using least squares. SCCNonlinearProblem can only be used for initialization of fully determined systems and hence will not be used here. To suppress this warning pass warn_initialize_determined = false. To make this warning into an error, pass fully_determined = true
â”” @ ModelingToolkit D:\bamboo.julia\packages\ModelingToolkit\Ay2JZ\src\problems\initializationproblem.jl:106
ODEProblem with uType Nothing and tType Float64. In-place: true
Initialization status: OVERDETERMINED
Non-trivial mass matrix: false
timespan: (0.0, 100.0)
u0: nothing
If I input empty initial conditions, there is no warning, but the solution remains empty.
empty doesn’t mean anything bad? It could just mean that it simplified everything and can be interpolated at any time.
Maybe I’m seeing this with an overly practical viewpoint, but generally a sensor should not change how a system behaves. In my example, I basically just want to monitor the force in the spring of a spring-mass system, using a dedicated sensor. This should not change the dynamics of the system. Or maybe I’m misunderstanding the use of sensors in MTK.
This situation does not show with e.g AccelerationSensor for instance, to monitor the mass acceleration.
About the empty solution, initial and final points are the same, so nothing happens. If I come back to the previous initial conditions showing a warning, the simulation fails with an InitialFailure
julia> sol_mass_sens = solve(prob, Rodas5())
retcode: InitialFailure
Interpolation: 1st order linear
t: 2-element Vector{Float64}:
0.0
100.0
u: 2-element Vector{Vector{Float64}}:
which doesn’t make more sense.
Ok, you can call me dumb.
For some reason, I thought that to measure the force through the spring I should connect the ForceSensor to the same flanges as the spring. But no, like for a true force sensor, this should be done is series…
This works perfectly fine… Thanks for the help.
using MIGALE
using ModelingToolkit
import ModelingToolkit: connect, t_nounits as t, D_nounits as D
using ModelingToolkitStandardLibrary
using DifferentialEquations
@named mass = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Mass(m=1)
@named spring = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Spring(k=1)
@named fix = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Fixed()
@named force = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.Force()
@named fsensor = ModelingToolkitStandardLibrary.Mechanical.TranslationalPosition.ForceSensor()
eqs = Equation[
connect(mass.flange, spring.flange_b)
connect(fix.flange, spring.flange_a)
]
@named model = ODESystem(eqs, t; systems=[mass, spring, fix])
sys = mtkcompile(model)
initial = Dict{Num,Any}([
mass.s => 1.
mass.v => 0.
]
)
prob = ODEProblem(sys, initial, (0.0, 100.0)) # Works
sol_mass_nosens = solve(prob, Rodas5())
eqs = Equation[
connect(fix.flange, spring.flange_a)
connect(spring.flange_b, fsensor.flange_a)
connect(fsensor.flange_b, mass.flange)
]
@named model = ODESystem(eqs, t; systems=[mass, spring, fix, fsensor])
sys = mtkcompile(model)
initial = Dict{Num,Any}([
mass.s => 1.
mass.v => 0.
]
)
prob = ODEProblem(sys, initial, (0.0, 100.0))
sol_mass_sens = solve(prob, Rodas5())
plot(sol_mass_nosens)
plot!(sol_mass_sens, color=:red, linestyle=:dash)
1 Like