JuliaControl / JuliaControl/RobustAndOptimalControl.jl
Hard to understand error message: Lengths of U2 (1:27) and Y1
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 67
- Forks
- 10
- Avg merge
- 1h 21m
- Merged PRs (30d)
- 3
Description
So I was working on my first larger block diagram, and trying to get everything in place. First I was meeting error messages giving me the name of an input/output that I was able to figure out. But after sorting out all that, I was presented with the following error message, after which I am quite stuck.
I am asking in this issue if maybe the error message should be improved on?
julia> bd = mk2_block_diagram_()
┌ Warning: Connecting single output to multiple inputs Y1=Union{Nothing, Int64}[1, 9, 8, 5, 20, 21, 22, 23, 24, 25, 11, 13, 12, 14, 3, 4, 6, 7, 16, 18, 17, 19, 15, 4, 11, 12, 21, 2, 10, 1]
└ @ ControlSystemsBase ~/.julia/packages/ControlSystemsBase/eWEYr/src/connections.jl:323
ERROR: Lengths of U2 (1:27) and Y1 (Union{Nothing, Int64}[1, 9, 8, 5, 20, 21, 22, 23, 24, 25, 11, 13, 12, 14, 3, 4, 6, 7, 16, 18, 17, 19, 15, 4, 11, 12, 21, 2, 10, 1]) must be equal
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] feedback(sys1::StateSpace{Continuous, Float64}, sys2::StateSpace{Continuous, Bool}; U1::Vector{Union{Nothing, Int64}}, Y1::Vector{Union{Nothing, Int64}}, U2::UnitRange{Int64}, Y2::UnitRange{Int64}, W1::Vector{Union{Nothing, Int64}}, Z1::Vector{Union{Nothing, Int64}}, W2::Vector{Union{Nothing, Int64}}, Z2::Vector{Union{Nothing, Int64}}, Wperm::Colon, Zperm::Colon, pos_feedback::Bool)
@ ControlSystemsBase ~/.julia/packages/ControlSystemsBase/eWEYr/src/connections.jl:332
[3] feedback(s1::NamedStateSpace{Continuous, StateSpace{Continuous, Float64}}, s2::NamedStateSpace{Continuous, StateSpace{Continuous, Bool}}; u1::Vector{Symbol}, w1::Vector{Symbol}, z1::Vector{Symbol}, y1::Vector{Symbol}, u2::Function, y2::Function, w2::Vector{Any}, z2::Vector{Any}, kwargs::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:pos_feedback,), Tuple{Bool}}})
@ RobustAndOptimalControl ~/.julia/packages/RobustAndOptimalControl/nd5G8/src/named_systems2.jl:367
[4] connect(systems::Vector{NamedStateSpace{Continuous, StateSpace{Continuous, Float64}}}; u1::Vector{Symbol}, y1::Vector{Symbol}, w1::Vector{Symbol}, z1::Vector{Symbol}, verbose::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ RobustAndOptimalControl ~/.julia/packages/RobustAndOptimalControl/nd5G8/src/named_systems2.jl:463
[5] connect(systems::Vector{NamedStateSpace{Continuous, StateSpace{Continuous, Float64}}}, pairs::Vector{Pair{Symbol, Symbol}}; kwargs::Base.Pairs{Symbol, Vector{Symbol}, Tuple{Symbol, Symbol}, NamedTuple{(:w1, :z1), Tuple{Vector{Symbol}, Vector{Symbol}}}})
@ RobustAndOptimalControl ~/.julia/packages/RobustAndOptimalControl/nd5G8/src/named_systems2.jl:467
[6] mk2_block_diagram_(; inner_feedback::Bool, outer_feedback::Bool)
@ Main ~/Documents/forsøk/spark_10_feedback/spark_10_feedback.jl:386
[7] mk2_block_diagram_()
@ Main ~/Documents/forsøk/spark_10_feedback/spark_10_feedback.jl:327
[8] top-level scope
@ REPL[256]:1
The code for the failing function:
function mk2_block_diagram(airspeed; params = init_pitch_params(), inner_feedback = true, outer_feedback = true)
integrator = tf([1], [1, 0])
dynamic_pressure = 0.5 * params.rho * airspeed^2
k0 = params.aoa_to_moment_gain_normalized
k1 = params.aoa_rate_to_moment_gain_normalized
back = dynamic_pressure * parallel(k0 * integrator, tf(k1 / max(airspeed, eps())))
# we assume the airflow is coming from pitch angle zero
feedback(inertia_tf(params = params), back)
my_named_tf = (tf, name) -> named_ss(ss(tf), u = Symbol("$(name)_u"), x = Symbol("$(name)_x"), y = Symbol("$(name)_y"))
only_first = arr -> [x[1] => y[1] for (x, y) = arr]
inertia = my_named_tf(inertia_tf(), :inertia) # output is pitch rate
pitch_int = my_named_tf(integrator, :pitch_int) # output is pitch angle
aoa_aero = my_named_tf(tf(dynamic_pressure * k0), :aoa_aero)
aoa_rate_aero = my_named_tf(tf(dynamic_pressure * k1 / max(eps(), airspeed)), :aoa_rate_aero)
aoa_int = my_named_tf(integrator, :aoa_int) # output is aoa angle, signal is aoa_rate otherwise system is not proper
hacker = my_named_tf(hacker_tf(), :hacker)
elev_aero = my_named_tf(elevator_to_aero_moments_tf(airspeed, params = params), :elev_aero)
props_ctrl = my_named_tf(mk2_inner_props_controller(), :props_ctrl)
elev_ctrl = my_named_tf(mk2_inner_elev_controller(), :elev_ctrl)
outer_ctrl = my_named_tf(mk2_outer_controller_tf(), :outer_ctrl)
inputs = [:pitch_ref
, :aoa_rate
, :disturbance
]
blocks = [
inertia
, pitch_int
, aoa_aero
, aoa_rate_aero
, aoa_int
, hacker
, elev_aero
, props_ctrl
, elev_ctrl
, outer_ctrl
]
splitters = [
splitter(:aoa_rate, 2)
, splitter(:pitch_int_y, 3)
, splitter(:outer_ctrl_y, 2)
, splitter(:inertia_y, 2)
]
sum_blocks = [
sumblock("aoa_int_u = aoa_rate1 - pitch_int_y1")
, sumblock("aoa_rate_aero_u = aoa_rate2 - pitch_int_y2")
, sumblock("inertia_u = aoa_aero_y + aoa_rate_aero_y + hacker_y + elev_aero_y + disturbance")
, sumblock(inner_feedback ? "props_ctrl_u = outer_ctrl_y1 - inertia_y1" : "props_ctrl_u = outer_ctrl_y1")
, sumblock(inner_feedback ? "elev_ctrl_u = outer_ctrl_y2 - inertia_y2" : "elev_ctrl_u = outer_ctrl_y2" )
, sumblock(outer_feedback ? "outer_ctrl_u = pitch_ref - pitch_int_y3" : "outer_ctrl_u = pitch_ref")
]
connections = vcat(
only_first([elev_ctrl.y => elev_aero.u
, props_ctrl.y => hacker.u
, aoa_int.y => aoa_aero.u
])
, [sys.y[1] => sys.y[1] for sys = sum_blocks] # need to connect sum blocks to real blocks
, vcat([[n => n for n = setdiff(sys.u, inputs)] for sys = sum_blocks]...)
, vcat([sys.u[1] => sys.u[1] for sys = splitters])
, :inertia_y3 => :pitch_int_u
)
# dump([
# :blocks => blocks
# , :splitters => splitters
# , :sum_blocks => sum_blocks
# , :connections => connections
# ])
connect(vcat(blocks, splitters, sum_blocks), connections, w1 = inputs, z1 = [sys.y[1] for sys = blocks])
end
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce mk2_block_diagram_() and trace the failure through ControlSystemsBase/src/connections.jl:332 and RobustAndOptimalControl/src/named_systems2.jl:367,463. Compare the reported U2 and Y1 connections with the inputs and outputs assembled in the example. Done means the failure message identifies the mismatched signals clearly enough to locate the faulty connection.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- developer-experience
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100