Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interconnect function strange behavior #952

Open
nodedge opened this issue Dec 26, 2023 · 3 comments
Open

Interconnect function strange behavior #952

nodedge opened this issue Dec 26, 2023 · 3 comments

Comments

@nodedge
Copy link

nodedge commented Dec 26, 2023

Hello,

I am testing the interconnect function to integrate it within nodedge editor, but I don't understand the behavior in the example_with_connections.

In particular, I have the following warning:

UserWarning: Unused input(s) in InterconnectedSystem: (0, 1)=sum.p.y[0]

And the step response is not the same as for the example_with_explicit_signals.

Can you please explain me what I am doing wrong?

Best regards.
Anthony.

import control as ct
import numpy as np


def example_with_explicit_signals():
    P = ct.tf2io([1], [1, 1], inputs="u", outputs="y")
    C = ct.tf2io([1], [1, 0], inputs="e", outputs="u")
    sumblk = ct.summing_junction(inputs=["ref", "-y"], output="e", name="sum")
    io_closed = ct.interconnect([sumblk, C, P], inplist=["ref"], outlist="y")
    print(io_closed)

    time = np.linspace(0, 10, 100)
    t, y = ct.input_output_response(io_closed, time, U=30, X0=[0, 15])
    print(y)

    return y


def example_with_connections():
    P = ct.tf2io([1], [1, 1], name="p", inputs=1, outputs=1, states="X0")
    C = ct.tf2io([1], [1, 0], name="c", inputs=1, outputs=1, states="X1")
    sumblk = ct.summing_junction(inputs=["ref", "p.y[0]"], output="e", name="sum")
    io_closed = ct.interconnect(
        [sumblk, C, P],
        inplist=["ref"],
        outlist="p.y[0]",
        connections=[
            ("p.u[0]", "c.y[0]"),
            ("c.u[0]", "sum.e"),
        ],
    )
    print(io_closed)

    time = np.linspace(0, 10, 100)
    t, y = ct.input_output_response(io_closed, time, U=30, X0=[0, 15])
    print(y)

    return y


if __name__ == "__main__":
    np.testing.assert_array_equal(
        example_with_explicit_signals(), example_with_connections()
    )
@murrayrm
Copy link
Member

murrayrm commented Dec 26, 2023

The error is happening because of the way that signals are named. In the command

sumblk = ct.summing_junction(inputs=["ref", "p.y[0]"], output="e", name="sum")

you are creating a system "sumblk" with inputs "ref" and "p.y[0]". When you list the connections in the interconnect function, you are not connecting the second signal (which is named "sum.p.y[0]") to anything, so you are getting a warning message.

The seemingly correct command to getting everything up like you want would be

connections=[
            ("p.u[0]", "c.y[0]"),
            ("c.u[0]", "sum.e"),
            ("sum.p.y[0]", "p.y[0]")
]

However, if you try that in the current main branch, you will get an error because signal names are not allowed to include '.' (not sure what version you are running, but apparently something earlier than did not have this check).

To get what (I think) you want, use

sumblk = ct.summing_junction(inputs=["ref", "p_y[0]"], output="e", name="sum")

and

io_closed = ct.interconnect(
        [sumblk, C, P],
        inplist=["ref"],
        outlist="p.y[0]",
        connections=[
            ["p.u[0]", "c.y[0]"],
            ["c.u[0]", "sum.e"],
            ["sum.p_y[0]", "-p.y[0]"]
        ],
    )

Note that in adddition to changing the signal names, I also changed the connections to be a list of lists, as required in the current main branch (that was a change when vector signals were introduced).

@nodedge
Copy link
Author

nodedge commented Dec 26, 2023

Thank you, Richard, it works now.

I am curious about why there is an asymmetry between the signals ref and p_y[0].
For the signal ref, there is an implicit and automatic connection between the signal coming from inplist and sum.ref.
Instead, for the signal p.y[0], we need to declare an explicit connection between p.y[0] and sum.p_y[0]. It may be because signal names in the summing junction cannot have dots. Nevertheless, we can name signals like system.signal, and the latter is also the signal name by default when the user does not specify one.
This leads to the following ambiguous case:

  • the user does not explicitly name the output signals of a system that is linked to a summing junction,
  • the summing junction cannot directly and implicitly link the signals coming from the source system to the internal signals of the summing junction (because it would imply two dots, which is forbidden).

I might be missing the reason that led you to remove the possibility of naming signals with a dot (and hence having double dots in summing junctions).

@murrayrm
Copy link
Member

The reason for now allowing the dot was because systems can be nested and so "a.b.y[0]" could mean the signal "b.y[0]" coming out of the block "a" or "a" could be an interconnected system with subsystem "b" and you could mean "y[0]" from that (internal) subsystem. This "nested" functionality is not actually implemented, so perhaps the better solution would just be to allow arbitrary signal names.

In terms of the asymmetry with the system input signal names (eg, "ref") and the internal connections, I agree that this should be generalized so that if you specify a signal name that is unique, then the system need not be specified.

I'm tagging this issue as an enhancement as a flag for someone (perhaps me, someday) to implement that functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants