Skip to content

BugFix: tf2ss now handles static gains #129

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

Merged
merged 1 commit into from
Feb 15, 2017

Conversation

roryyorke
Copy link
Contributor

Fix for #81.

@coveralls
Copy link

coveralls commented Jan 4, 2017

Coverage Status

Changes Unknown when pulling a44305b on roryyorke:rory/tf2ss-static-gain into ** on python-control:master**.

@slivingston slivingston self-assigned this Jan 6, 2017
@slivingston
Copy link
Member

Could you split testTf2ssStatic from a44305b#diff-34ce1aa9250b93553151bda70aa98a07 into two separate tests? Use slycot_check as the splitting boundary.

Following my comment on PR #122, tests should not partially change when Slycot is present or not. Otherwise, debugging efficiency is negatively impacted.

@roryyorke
Copy link
Contributor Author

You mean using @unittest.skipIf(not slycot_check(), "slycot not installed") as elsewhere in the test suite?

Sure, will do.

@roryyorke roryyorke force-pushed the rory/tf2ss-static-gain branch from a44305b to 5c839c2 Compare January 6, 2017 18:58
@roryyorke
Copy link
Contributor Author

It looks like this is actually a bug in Slycot, as speculated in [1]; I can get SLICOT's TD04AD to convert a static TF. I'll see if I can wrap my mind around f2py's syntax and fix this in Slycot. In that case we can keep the unit tests in this PR, but the change to statesp.py will be different, and the code will be much simpler.

[1] https://github.com/roryyorke/python-control/blob/5c839c205dce8e072909509545266a466d4a2404/control/statesp.py#L669-L671

@slivingston
Copy link
Member

Because changes from python-control/Slycot#5 are now in Slycot, the only remaining case before we can close #81 is when Slycot is not installed.

@roryyorke Some of the changes from your original commit in this PR might be able to address the case of no slycot. In particular,

D = empty((sys.outputs,sys.inputs),dtype=float)
for i,j in itertools.product(range(sys.outputs),range(sys.inputs)):
    D[i,j] = sys.num[i][j][0] / sys.den[i][j][0]
return StateSpace([], [], [], D, sys.dt)

@roryyorke
Copy link
Contributor Author

Is your idea to have three cases: (1) static gain (SISO or MIMO), (2) with-Slycot (any dynamic), (3) no-Slycot (SISO dynamic only) ?

We could add a case (0), namely empty systems (or this could be handled in (1)); this would let us sidestep the Slycot issues with empty systems you identified in in the related Slycot PR.

@slivingston
Copy link
Member

Unless I am missing something, with Slycot, static gain does not need to be treated as a special case, thanks to your patches to Slycot.

However, when Slycot is not installed, static gain would be treated separately.

@slivingston
Copy link
Member

so, the cases are:

  1. with Slycot
  2. static gains, no Slycot
  3. SISO, no Slycot

Before creating a special case to handle empty systems (as noticed during review of python-control/Slycot#5), we might wait until there is a motivating application.

@roryyorke roryyorke force-pushed the rory/tf2ss-static-gain branch from 5c839c2 to 02080e0 Compare February 11, 2017 12:24
@roryyorke
Copy link
Contributor Author

CI won't pass without updated Slycot; it passes on my Ubuntu 14.04 x64 system, with Conda Python 3.5.2, both with Slycot 9a098d12, and without Slycot.

@slivingston
Copy link
Member

I also demonstrated success on your tests testTf2ssStaticSiso and testTf2ssStaticMimo on a GNU/Linux system using Python versions 3.5.2 and 2.7.9, each with and without the current tip of master branch Slycot, 001b45d437ae7f9e9f3ff0d82db339897d548cab

Tomorrow I will work on releasing the next version of Slycot.

@coveralls
Copy link

coveralls commented Feb 14, 2017

Coverage Status

Coverage decreased (-0.1%) to 77.352% when pulling 02080e0 on roryyorke:rory/tf2ss-static-gain into 8caf661 on python-control:master.

"""Regression: tf2ss for MIMO static gain"""
import control
# 2x3 TFM
gmimo = control.tf2ss(control.tf([[ [23], [3], [5] ], [ [-1], [0.125], [101.3] ]],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you select these coefficients?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an arbitrary selection of numbers over a (small) range of magnitudes and signs; in all cases the ratios are exactly representable with low precision (see d just below), so I could use np.assert_array_equal().

lti_sys = lti(squeeze(sys.num), squeeze(sys.den))
return StateSpace(lti_sys.A, lti_sys.B, lti_sys.C, lti_sys.D,
sys.dt)
# No Slycot. Scipy tf->ss can't handle MIMO, but static MIMO is an easy special case we can check for here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment lines should have length no more than 79 char. PEP 8 recommends 72 for the case of comments, but in my experience a uniform max line length is easier to follow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will fix. Sorry, it's pretty obvious now that I look at it. Emacs fills this to 68 columns, which in this case doesn't waste an extra line:

            # No Slycot.  Scipy tf->ss can't handle MIMO, but static
            # MIMO is an easy special case we can check for here

if (sys.inputs != 1 or sys.outputs != 1):
raise TypeError("No support for MIMO without slycot")

# TODO: do we want to squeeze first and check dimenations?
Copy link
Member

@slivingston slivingston Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should "dimenations" be "dimensions"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't take the credit for this one, the comment was there already ;). Not sure it's applicable anymore: the check that sys.inputs and sys.outputs are both 1 implies that squeeze will bring num and den to 1-D?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. The comment is obsolete after the addition in commit c90a399 of the check that sys.inputs = sys.outputs = 1.

I am planning to review and perform maintenance on documentation and code comments, so I can delete this comment at that time.

@slivingston
Copy link
Member

As you might have noticed, a current Slycot release was made, and now the CI jobs for this PR are passing.

Aside from my request about line length and question about the static gains MIMO test case, changes here are good to go.

Check for static-gain (i.e., constant) transfer function matrix, and
handle specially.

Added unit tests for static SISO and MIMO plants.
@roryyorke roryyorke force-pushed the rory/tf2ss-static-gain branch from 02080e0 to c5a8ad3 Compare February 14, 2017 20:13
@coveralls
Copy link

coveralls commented Feb 14, 2017

Coverage Status

Coverage decreased (-0.1%) to 77.352% when pulling c5a8ad3 on roryyorke:rory/tf2ss-static-gain into 8caf661 on python-control:master.

@slivingston slivingston merged commit c5a8ad3 into python-control:master Feb 15, 2017
@roryyorke roryyorke deleted the rory/tf2ss-static-gain branch February 15, 2017 17:04
@murrayrm murrayrm added this to the 0.8.0 milestone Dec 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants