Skip to content

Hard to understand error message: Lengths of U2 (1:27) and Y1 #90

@tallakt

Description

@tallakt

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions