Skip to content

Conversation

akshanshbhatt
Copy link
Member

@akshanshbhatt akshanshbhatt commented Jul 20, 2021

References to other Issues or PRs

Brief description of what is fixed or changed

Implement common graphical analyses related to control theory.

Other comments

Checklist:

  • Pole-Zero Plot
  • Step Response
  • Impulse Response
  • Ramp Response
  • Bode Plot
  • Methods for getting numerical data
  • Docs
  • Tests

Future Work:

Release Notes

  • physics.control
    • Added common plots related to control theory.

@sympy-bot
Copy link

sympy-bot commented Jul 20, 2021

Hi, I am the SymPy bot (v161). I'm here to help you write a release notes entry. Please read the guide on how to write release notes.

Your release notes are in good order.

Here is what the release notes will look like:

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.9.

Click here to see the pull request description that was parsed.
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->


#### Brief description of what is fixed or changed

Implement common graphical analyses related to control theory.

#### Other comments

__Checklist:__

- [x] Pole-Zero Plot
- [x] Step Response
- [x] Impulse Response
- [x] Ramp Response
- [x] Bode Plot
- [x] Methods for getting numerical data
- [x] Docs
- [x] Tests

__Future Work:__

- [ ] ~~Root Locus~~ (Effective sampling needed. See https://github.com/sympy/sympy/pull/21763#discussion_r675772024 and https://github.com/sympy/sympy/pull/21763#discussion_r675882746)
- [ ] ~~Nyquist Plot **~~ (Out of scope of my proposed project. Will add sometime in the future along with Nichols plot)

#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers.

or if no release note(s) should be included use:

NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* physics.control
  * Added common plots related to control theory.
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@sympy-bot
Copy link

sympy-bot commented Jul 20, 2021

🟠

Hi, I am the SymPy bot (v161). I've noticed that some of your commits add or delete files. Since this is sometimes done unintentionally, I wanted to alert you about it.

This is an experimental feature of SymPy Bot. If you have any feedback on it, please comment at sympy/sympy-bot#75.

The following commits add new files:

  • 44819e7:
    • sympy/physics/control/control_plots.py
  • 250784e:
    • doc/src/modules/physics/control/control_plots.rst
  • cf171a2:
    • sympy/physics/control/tests/test_control_plots.py

If these files were added/deleted on purpose, you can ignore this message.

@akshanshbhatt
Copy link
Member Author

Step Response:

For TransferFunction(4, s**2 + 2*s + 10, s)

MATLAB

image

THIS IMPLEMENTATION

output

For TransferFunction(8*s**2 + 18*s + 32, 1*s**3 + 6*s**2 + 14*s + 24, s)

MATLAB

image

THIS IMPLEMENTATION

output2

@akshanshbhatt
Copy link
Member Author

Pole-Zero Plot

TransferFunction(2*s**2 + 5*s + 1, s**2 + 3*s + 5, s)

MATLAB

image

THIS IMPLEMENTATION

pole_zero_1

TransferFunction(s - 1, s**4 + 6*s**3 + 12*s**2 + 11*s + 6, s)

MATLAB

image

THIS IMPLEMENTATION

pole_zero_2

Copy link
Member

@namannimmo10 namannimmo10 left a comment

Choose a reason for hiding this comment

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

These plots look really nice!

@akshanshbhatt
Copy link
Member Author

This PR
image
MATLAB
image

(For TransferFunction(1*s**2 + 0.1*s + 7.5, 1*s**4 + 0.12*s**3 + 9*s**2, s), First example on - https://in.mathworks.com/help/ident/ref/lti.bode.html)

@namannimmo10, the text-overflow/overlap shouldn't be an issue, in my opinion, right?

@akshanshbhatt
Copy link
Member Author

Is there some way to fix the axis on the extreme left instead of floating in the middle of the screen (like in MATLAB)?
And also,
How can we turn the grid on while using sympy's native plot() (sympy.plotting.plot) method?

@akshanshbhatt
Copy link
Member Author

image

After changing the marker size.

@github-actions
Copy link

github-actions bot commented Jul 21, 2021

Benchmark results from GitHub Actions

Lower numbers are good, higher numbers are bad. A ratio less than 1
means a speed up and greater than 1 means a slowdown. Green lines
beginning with + are slowdowns (the PR is slower then master or
master is slower than the previous release). Red lines beginning
with - are speedups.

Significantly changed benchmark results (PR vs master)

Significantly changed benchmark results (master vs previous release)

       before           after         ratio
     [ed9a550f]       [ad4cbf28]
     <sympy-1.8^0>                 
-      1.11±0.01s        151±0.4ms     0.14  dsolve.TimeDsolve01.time_dsolve
-      10.3±0.01s          5.04±0s     0.49  integrate.TimeIntegrationRisch02.time_doit(100)
-      10.2±0.01s          5.03±0s     0.49  integrate.TimeIntegrationRisch02.time_doit_risch(100)
-      85.2±0.6μs       33.3±0.2μs     0.39  matrices.TimeDiagonalEigenvals.time_eigenvals
-         106±2μs       66.6±0.7μs     0.63  matrices.TimeMatrixGetItem.time_ImmutableDenseMatrix_getitem
-       106±0.7μs         67.1±1μs     0.64  matrices.TimeMatrixGetItem.time_ImmutableSparseMatrix_getitem
-       104±0.3μs         67.2±1μs     0.65  matrices.TimeMatrixGetItem.time_MutableSparseMatrix_getitem
-      96.6±0.4μs      60.8±0.06μs     0.63  solve.TimeMatrixArithmetic.time_dense_add(10, 0)
+     13.2±0.05μs       21.9±0.2μs     1.66  solve.TimeMatrixArithmetic.time_dense_add(3, 0)
+     15.5±0.05μs       33.7±0.3μs     2.17  solve.TimeMatrixArithmetic.time_dense_add(3, 5)
+     22.9±0.08μs      43.3±0.09μs     1.89  solve.TimeMatrixArithmetic.time_dense_add(4, 5)
+      42.1±0.2μs       70.5±0.2μs     1.67  solve.TimeMatrixArithmetic.time_dense_add(6, 5)
-     1.42±0.01ms        260±0.6μs     0.18  solve.TimeMatrixArithmetic.time_dense_multiply(10, 0)
-      55.0±0.4μs       28.3±0.1μs     0.52  solve.TimeMatrixArithmetic.time_dense_multiply(3, 0)
+      83.7±0.8μs        151±0.9μs     1.81  solve.TimeMatrixArithmetic.time_dense_multiply(3, 5)
-       117±0.6μs      36.0±0.07μs     0.31  solve.TimeMatrixArithmetic.time_dense_multiply(4, 0)
-         342±2μs       74.6±0.1μs     0.22  solve.TimeMatrixArithmetic.time_dense_multiply(6, 0)
-       104±0.6μs       47.1±0.2μs     0.45  solve.TimeMatrixOperations.time_det(3, 0)
-       189±0.4μs        113±0.3μs     0.60  solve.TimeMatrixOperations.time_det(3, 2)
-       179±0.5μs        104±0.8μs     0.58  solve.TimeMatrixOperations.time_det(3, 5)
-         106±3μs       47.1±0.1μs     0.44  solve.TimeMatrixOperations.time_det_bareiss(3, 0)
-         191±1μs        113±0.3μs     0.59  solve.TimeMatrixOperations.time_det_bareiss(3, 2)
-         182±2μs        104±0.2μs     0.57  solve.TimeMatrixOperations.time_det_bareiss(3, 5)
-       106±0.4μs       47.3±0.4μs     0.45  solve.TimeMatrixOperations.time_det_berkowitz(3, 0)
-         191±1μs          114±2μs     0.60  solve.TimeMatrixOperations.time_det_berkowitz(3, 2)
-       179±0.3μs        106±0.7μs     0.59  solve.TimeMatrixOperations.time_det_berkowitz(3, 5)
+         822±5μs      1.31±0.01ms     1.59  solve.TimeMatrixOperations.time_det_berkowitz(4, 0)
+         982±2μs      1.87±0.03ms     1.90  solve.TimeMatrixOperations.time_det_berkowitz(4, 2)
+        1.02±0ms      1.98±0.01ms     1.94  solve.TimeMatrixOperations.time_det_berkowitz(4, 5)
+       303±0.8μs          501±1μs     1.65  solve.TimeMatrixOperations.time_rank(3, 0)
+       474±0.5μs          756±1μs     1.59  solve.TimeMatrixOperations.time_rank(4, 0)
+       140±0.1μs        210±0.4μs     1.50  solve.TimeMatrixOperations.time_rref(3, 0)
-     5.97±0.01ms      3.29±0.03ms     0.55  solve.TimeRationalSystem.time_linsolve(10)
-     1.20±0.01ms          760±4μs     0.63  solve.TimeRationalSystem.time_linsolve(5)
+     7.42±0.01ms      11.2±0.03ms     1.51  solve.TimeSparseSystem.time_linear_eq_to_matrix(30)
-     3.90±0.03ms      2.47±0.03ms     0.63  solve.TimeSparseSystem.time_linsolve_eqs(30)

Full benchmark results can be found as artifacts in GitHub Actions
(click on checks at the top of the PR).

@namannimmo10
Copy link
Member

Is there some way to fix the axis on the extreme left instead of floating in the middle of the screen (like in MATLAB)?

I'm not aware. If there's a way to obtain a better-looking (with no overlaps or overflows) bode plot using matplotlib or other backends, you can go with that.

@akshanshbhatt
Copy link
Member Author

TransferFunction(2*s**2 + 5*s + 1, s**2 + 2*s + 3, s)

image
(MATLAB)
rootloci
(This PR)

TransferFunction(s + 7, s*(s + 5)*(s + 15)*(s + 20), s)

image
(MATLAB)
rootloci_2
(This PR)

@akshanshbhatt
Copy link
Member Author

With this, all the plots are complete.
Some minor API changes are required, along with docs and tests, which I will try to finish before next week.

Let me know if you find any issues.

"""
system = system.doit() # Get the equivalent TransferFunction object.

num_poly = Poly(system.num, system.var).all_coeffs()
Copy link
Member

Choose a reason for hiding this comment

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

I would not use Poly for this implementation; It doesn't work well with time-delay terms.

>>> G = TransferFunction(s*exp(-s), s**2 + 2*s + 1, s)
>>> pole_zero(G)
Traceback (most recent call last):
  File "/home/namannimmo/oss/sympy/sympy/polys/polyutils.py", line 211, in _parallel_dict_from_expr_if_gens
    monom[indices[base]] = exp
KeyError: exp(-s)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/namannimmo/oss/sympy/sympy/physics/control/control_plots.py", line 28, in pole_zero
    num_poly = Poly(system.num, system.var).all_coeffs()
  File "/home/namannimmo/oss/sympy/sympy/polys/polytools.py", line 164, in __new__
    return cls._from_expr(rep, opt)
  File "/home/namannimmo/oss/sympy/sympy/polys/polytools.py", line 293, in _from_expr
    rep, opt = _dict_from_expr(rep, opt)
  File "/home/namannimmo/oss/sympy/sympy/polys/polyutils.py", line 368, in _dict_from_expr
    rep, gens = _dict_from_expr_if_gens(expr, opt)
  File "/home/namannimmo/oss/sympy/sympy/polys/polyutils.py", line 307, in _dict_from_expr_if_gens
    (poly,), gens = _parallel_dict_from_expr_if_gens((expr,), opt)
  File "/home/namannimmo/oss/sympy/sympy/polys/polyutils.py", line 216, in _parallel_dict_from_expr_if_gens
    raise PolynomialError("%s contains an element of "
sympy.polys.polyerrors.PolynomialError: exp(-s) contains an element of the set of generators.

Copy link
Member Author

@akshanshbhatt akshanshbhatt Jul 23, 2021

Choose a reason for hiding this comment

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

The reason behind using Poly() was speed. I was using NumPy for root-locus and getting a huge performance advantage because- (a) SymPy is a symbolic computation library and NumPy is a numeric computation library. (b) Matplotlib requires NumPy for internal numeric computation and hence NumPy is also a listed dependency for matplotlib. It is installed with matplotlib.

image

Also just to be clear, these plots will not support transfer functions with time delay. Maybe I'll allow time-delay in Pole-Zero because time delay doesn't affect the poles and zeroes of the system.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It is possible to use sympy with other plotting backends that do not necessarily use numpy:
https://pypi.org/project/sympy-plot-backends/

Generally when sympy has numeric routines they are more accurate than numpy's:

In [8]: p = expand(prod(x - i for i in range(1, 21)))

In [9]: nroots(p)
Out[9]: 
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15
.0, 16.0, 17.0, 18.0, 19.0, 20.0]

In [10]: numpy.roots(Poly(p).all_coeffs())
Out[10]: 
array([19.99980929, 19.00190982, 17.99092135, 17.02542715, 15.94628672,
       15.0754938 , 13.91475559, 13.07431403, 11.95328325, 11.02502293,
        9.99041304,  9.00291529,  7.99935583,  7.000102  ,  5.99998925,
        5.00000067,  3.99999998,  3.        ,  2.        ,  1.        ])

Copy link
Member Author

@akshanshbhatt akshanshbhatt Jul 23, 2021

Choose a reason for hiding this comment

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

Plotting backend is not an issue here. Whichever backend we may use, it requires efficient sampling to generate plots. Some form of numerical computation will always occur under the hood. SymPy undoubtedly is more accurate in numerical operations. Still, during sampling with a large number of points (10000), accuracy hardly matters, especially when a much faster approach (more than 1000 times) is accurate up to 3-4 decimal places.

Copy link
Collaborator

Choose a reason for hiding this comment

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

is accurate up to 3-4 decimal places.

The accuracy can degrade much more than that.

The idea with using a symbolic library is that you should have greater confidence in things like the accuracy of any computed result even if that means waiting longer for things to be computed. It also means that different approaches are often better to make something efficient.

As an example your root_locus function computes the roots of 10000 different polynomials. Why 10000? No one needs that many points in the plot. Many of the lines are just joining points on the real axis. To plot a straight line you only need to know its start and end and those can be computed exactly. Then you don't need to evaluate the polynomial at 10000 points.

I'm not sure I've understood the calculation that you want precisely but I think it's something like this:

In [35]: eq
Out[35]: k⋅(s + 7) + s⋅(s + 5)⋅(s + 15)⋅(s + 20)

In [36]: discriminant(eq)
Out[36]: 
      4          3             2                               
- 27k  + 47088k  - 37907500k  + 3881250000k + 1265625000000

In [37]: nroots(discriminant(eq))
Out[37]: [-130.564918275438, 307.765516989741, 783.399700642849 - 743.513266939402, 783.399700642849 + 743.513266939402]

The positive real roots for k are the points on the real axis where lines start and end. This now shows you what values of k are interesting for the plot.

Copy link
Member Author

Choose a reason for hiding this comment

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

For TransferFunction(2*s**2 + 5*s + 1, s**2 + 3*s + 5, s)

  • If num=10000 (sampled 10000 times, default)

    scatter_rootLocus_10k

    The scatter plot looks like this.
    And the actual root-locus plot (corresponding to the regression of these sampled points) looks like this-

    rl

Similarly,

  • If num=1000

    1k

    1k_plot

  • If num=300

    scatter_300

    plot_300

To plot a straight line you only need to know its start and end and those can be computed exactly. Then you don't need to evaluate the polynomial at 10000 points.

Straight Lines in root locus plots are not very common. In root-locus plots, we plot the movement of the roots of the polynomial den+ k*num when k varies from 0 to inf. As you can tell when k is 0 we get the roots of den (poles) and as k approaches inf, the roots of den + k*num are roots of num only (zeros). Therefore, when num and den have the same degree, the root locus plot is a path from poles to zeros of the transfer function. This is not always a straight line.

equal

Only one is a straight line path here and knowing this fact can't help us in any way. I don't understand how knowing the discriminant of the polynomial will help us in knowing the points on the rl plot. Maybe I'm missing something.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Straight Lines in root locus plots are not very common.

Your example with num=1000 illustrates the point I wanted to make perfectly. To generate the plot you compute the roots of the polynomial for 1000 different values of k ranging from 0 to kmax where kmax is arbitrarily chosen to be 400. Out of those 1000 values of k only 4 have non-real roots so the other 996 polynomials whose roots are computed are only used to plot two straight lines. The straight line could be computed more efficiently and more accurately by simply computing its start and end points which you can do like this:

In [93]: k, s = symbols('k, s')

In [94]: n, d = 2*s**2 + 5*s + 1, s**2 + 3*s + 5

In [95]: eq = d + k*n

In [96]: eq
Out[96]: 
  ⎛   22          
k⋅⎝2s  + 5s + 1+ s  + 3s + 5

In [97]: nroots(n) # k = oo
Out[97]: [-2.28077640640441, -0.219223593595585]

In [98]: discriminant(eq, s)
Out[98]: 
    2            
17k  - 14k - 11

In [99]: nroots(discriminant(eq, s))
Out[99]: [-0.491899499749248, 1.31542891151395]

In [100]: roots(discriminant(eq, s), multiple=True)
Out[100]: 
⎡7    2⋅√59  7    2⋅√59⎤
⎢── - ─────, ── + ─────⎥
⎣17     17   17     17In [101]: eq.subs(k, roots(discriminant(eq, s), multiple=True)[1])
Out[101]: 
 27    2⋅√59⎞ ⎛   2s  + 3s + ⎜── + ─────⎟⋅⎝2s  + 5s + 1+ 517     17In [102]: roots(eq.subs(k, roots(discriminant(eq, s), multiple=True)[1]), s)
Out[102]: {-9 +59: 2}

In [103]: list(_)[0].n()
Out[103]: -1.31885425213139

Your suggestion to use num=10000 and compute the roots of 10000 polynomials is a workaround for having the wrong value of kmax. In fact by computing the roots of the discriminant it is possible to compute what the relevant values of k are.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fine. I get your point now. But there is still an issue. You see, with your calculations, we get these points:

image

Which is basically poles and zeroes of the Transfer Function + The point where the discriminant is zero (equal roots). I agree that for the two straight lines on the axis, this will work fine but what about the two symmetric arms of the curve?
We cannot plot them by simply knowing the start and endpoints. We still need to compute the roots of the polynomials from 0 to k_c (value of k for which the 0 discriminant point is reached) in uniform intervals.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We still need to compute the roots of the polynomials from 0 to k_c

Yes, but we don't need 10000 points to plot the curve. The num=10000 plot above shows that an acceptable plot is obtained from only 40 points (since the other 9960 points are on the real axis).

I expect that uniform spacing is not optimal. Naturally I would guess that something like logarithmic or harmonic spacing would be better. You can see in the num=10000 plot that using uniform intervals for k does not lead to a uniform distance between the points in the plot.

Ideally the curve would be generated using pseudo-arc-length continuation so you can generate them at a fixed 2D distance within the plot but that's probably more complicated than it is worth.

@namannimmo10
Copy link
Member

@ilayn, @murrayrm: please take a look.

@ilayn
Copy link

ilayn commented Jul 23, 2021

Looks very nice ! Much appreciated

For the step responses, I'd suggest my annoying pair of systems Transfer(1,[1,1001,1000]) and Transfer([1, 2, 0],[1,1001,1000]) for testing.

I'm a bit worried about the inverse laplace way since fast poles might trip up the exponential calculations say pole at -120 is no problem for numeric step responses but exp(-120*t) might underflow too quickly. Emphasis on might :D

@namannimmo10
Copy link
Member

You can set the linestyle as 'dotted' (or something else) so that these RGB colors are differentiable on the axis;
tf

@plaes
Copy link
Contributor

plaes commented Jul 27, 2021

Although this is a cool and much wanted feature, I'm not that sure whether it makes sense to put these plotting functions in as public API.

Although it would be nice to have out-of-the box plotting tools, we end up with a lot of customization and localization issues which eventually forces users to create a copy of existing functionality anyway if they want to do even the simplest things like changing the plot titles and labels.

@oscarbenjamin
Copy link
Collaborator

if they want to do even the simplest things like changing the plot titles and labels.

I think that the solution to that is that the plotting APIs should expose the lower level a bit so it's easy to e.g. get the matplotlib handle for the figure and add a title. At the same time any plotting APIs should make it easier to just get the underlying data so that they can be used with different plotting libraries.

CC @Davide-sd

@akshanshbhatt akshanshbhatt changed the title [WIP] Add graphical analyses in physics.control Add graphical analyses in physics.control Aug 16, 2021
Copy link
Member

@namannimmo10 namannimmo10 left a comment

Choose a reason for hiding this comment

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

Great! Can you finish this off by showing in the PR how all the plots look like?

@akshanshbhatt
Copy link
Member Author

Can you finish this off by showing in the PR how all the plots look like?

Sure!

These are all the plots from the documentation page rendered on my local -

image
image
image
image
image

All these plots will be visible on the doc page after merging this PR.

@namannimmo10
Copy link
Member

Can you check locally whether it is all rendering fine? Some cleanups might also be needed.

We can improve these plots in the future. I can merge this tonight.

@akshanshbhatt
Copy link
Member Author

Can you check locally whether it is all rendering fine? Some cleanups might also be needed.

Do you mean the docs?

@namannimmo10
Copy link
Member

Yes!

@akshanshbhatt
Copy link
Member Author

akshanshbhatt commented Aug 17, 2021

Yes!

Have a look. Updated to the latest commit.

Edit: https://docs.sympy.org/dev/modules/physics/control/control_plots.html Now you can see it here.

Copy link
Member

@namannimmo10 namannimmo10 left a comment

Choose a reason for hiding this comment

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

👍 Thank you!

@namannimmo10 namannimmo10 merged commit 801b104 into sympy:master Aug 17, 2021
@akshanshbhatt akshanshbhatt deleted the Plots branch August 17, 2021 16:18
@oscarbenjamin
Copy link
Collaborator

Having just released sympy 1.9 I've found that the tests added here fail:

$ bin/test sympy/physics/control/tests/test_control_plots.py 
======================================== test process starts ========================================
executable:         /home/oscar/current/sympy/37venv/bin/python  (3.7.10-final-0) [CPython]
architecture:       64-bit
cache:              yes
ground types:       gmpy 2.0.8
numpy:              1.21.0
random seed:        40766605
hash randomization: on (PYTHONHASHSEED=3506573775)

sympy/physics/control/tests/test_control_plots.py[6] .F.FFF                                    [FAIL]

_____________________________________________________________________________________________________
_________________ sympy/physics/control/tests/test_control_plots.py:test_pole_zero __________________
Traceback (most recent call last):
  File "/home/oscar/current/sympy/sympy.git/sympy/physics/control/tests/test_control_plots.py", line 100, in test_pole_zero
    ((0.0,), ((-0.5000000000000004+0.8660254037844395j),
AssertionError
_____________________________________________________________________________________________________
______________ sympy/physics/control/tests/test_control_plots.py:test_impulse_response ______________
Traceback (most recent call last):
  File "/home/oscar/current/sympy/sympy.git/sympy/physics/control/tests/test_control_plots.py", line 192, in test_impulse_response
    assert impulse_res_tester(tf3, exp3)
AssertionError
_____________________________________________________________________________________________________
_______________ sympy/physics/control/tests/test_control_plots.py:test_step_response ________________
Traceback (most recent call last):
  File "/home/oscar/current/sympy/sympy.git/sympy/physics/control/tests/test_control_plots.py", line 241, in test_step_response
    assert step_res_tester(tf3, exp3)
AssertionError
_____________________________________________________________________________________________________
_______________ sympy/physics/control/tests/test_control_plots.py:test_ramp_response ________________
Traceback (most recent call last):
  File "/home/oscar/current/sympy/sympy.git/sympy/physics/control/tests/test_control_plots.py", line 283, in test_ramp_response
    assert ramp_res_tester(tf3, 10, exp3, 1.5)
AssertionError

======================== tests finished: 2 passed, 4 failed, in 4.73 seconds ========================
DO *NOT* COMMIT!

I guess these tests are not properly running in CI and also they seem to be incorrect.

@akshanshbhatt
Copy link
Member Author

I guess these tests are not properly running in CI and also they seem to be incorrect.

I will try to debug it soon.

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

Successfully merging this pull request may close these issues.

7 participants