Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added option for computing anti-stabilizing solutions of Riccati equations#281

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
murrayrm merged 6 commits intopython-control:masterfromdbankmann:master
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions.travis.yml
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,8 +51,10 @@ before_install:
- conda create -q -n test-environment python="$TRAVIS_PYTHON_VERSION" pip coverage
- source activate test-environment
# Install openblas if slycot is being used
# also install scikit-build for the build process
- if [[ "$SLYCOT" != "" ]]; then
conda install openblas;
conda install openblas;
conda install -c conda-forge scikit-build;
fi
# Make sure to look in the right place for python libraries (for slycot)
- export LIBRARY_PATH="$HOME/miniconda/envs/test-environment/lib"
Expand All@@ -65,10 +67,11 @@ install:
- conda install $SCIPY matplotlib
# Build slycot from source
# For python 3, need to provide pointer to python library
# Use "Unix Makefiles" as generator, because Ninja cannot handle Fortran
#! git clone https://github.com/repagh/Slycot.git slycot;
- if [[ "$SLYCOT" != "" ]]; then
git clone https://github.com/python-control/Slycot.git slycot;
cd slycot; python setup.py install; cd ..;
cd slycot; python setup.py install -G "Unix Makefiles"; cd ..;
fi

# command to run tests
Expand Down
39 changes: 28 additions & 11 deletionscontrol/mateqn.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -411,7 +411,7 @@ def dlyap(A,Q,C=None,E=None):

#### Riccati equation solvers care and dare

def care(A,B,Q,R=None,S=None,E=None):
def care(A, B, Q,R=None,S=None,E=None, stabilizing=True):
""" (X,L,G) = care(A,B,Q,R=None) solves the continuous-time algebraic Riccati
equation

Expand DownExpand Up@@ -527,7 +527,11 @@ def care(A,B,Q,R=None,S=None,E=None):
raise e

try:
X,rcond,w,S_o,U,A_inv = sb02md(n,A,G,Q,'C')
if stabilizing:
sort = 'S'
else:
sort = 'U'
X, rcond, w, S_o, U, A_inv = sb02md(n, A, G, Q, 'C', sort=sort)
except ValueError as ve:
if ve.info < 0 or ve.info > 5:
e = ValueError(ve.message)
Expand DownExpand Up@@ -613,8 +617,12 @@ def care(A,B,Q,R=None,S=None,E=None):
# Solve the generalized algebraic Riccati equation by calling the
# Slycot function sg02ad
try:
rcondu,X,alfar,alfai,beta,S_o,T,U,iwarn = \
sg02ad('C','B','N','U','N','N','S','R',n,m,0,A,E,B,Q,R,S)
if stabilizing:
sort = 'S'
else:
sort = 'U'
rcondu, X, alfar, alfai, beta, S_o, T, U, iwarn = \
sg02ad('C', 'B', 'N', 'U', 'N', 'N', sort, 'R', n, m, 0, A, E, B, Q, R, S)
except ValueError as ve:
if ve.info < 0 or ve.info > 7:
e = ValueError(ve.message)
Expand DownExpand Up@@ -671,7 +679,7 @@ def care(A,B,Q,R=None,S=None,E=None):
else:
raise ControlArgument("Invalid set of input parameters.")

def dare(A,B,Q,R,S=None,E=None):
def dare(A, B, Q, R,S=None,E=None, stabilizing=True):
""" (X,L,G) = dare(A,B,Q,R) solves the discrete-time algebraic Riccati
equation

Expand All@@ -692,8 +700,8 @@ def dare(A,B,Q,R,S=None,E=None):
matrix :math:`G = (B^T X B + R)^{-1} (B^T X A + S^T)` and the closed loop
eigenvalues L, i.e., the eigenvalues of A - B G , E.
"""
if S is not None or E is not None:
return dare_old(A, B, Q, R, S, E)
if S is not None or E is not None or not stabilizing:
return dare_old(A, B, Q, R, S, E, stabilizing)
else:
Rmat = asmatrix(R)
Qmat = asmatrix(Q)
Expand All@@ -702,7 +710,7 @@ def dare(A,B,Q,R,S=None,E=None):
L = eigvals(A - B.dot(G))
return X, L, G

def dare_old(A,B,Q,R,S=None,E=None):
def dare_old(A, B, Q, R,S=None,E=None, stabilizing=True):
# Make sure we can import required slycot routine
try:
from slycot import sb02md
Expand DownExpand Up@@ -795,7 +803,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
raise e

try:
X,rcond,w,S,U,A_inv = sb02md(n,A,G,Q,'D')
if stabilizing:
sort = 'S'
else:
sort = 'U'

X, rcond, w, S, U, A_inv = sb02md(n, A, G, Q, 'D', sort=sort)
except ValueError as ve:
if ve.info < 0 or ve.info > 5:
e = ValueError(ve.message)
Expand DownExpand Up@@ -884,8 +897,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
# Solve the generalized algebraic Riccati equation by calling the
# Slycot function sg02ad
try:
rcondu,X,alfar,alfai,beta,S_o,T,U,iwarn = \
sg02ad('D','B','N','U','N','N','S','R',n,m,0,A,E,B,Q,R,S)
if stabilizing:
sort = 'S'
else:
sort = 'U'
rcondu, X, alfar, alfai, beta, S_o, T, U, iwarn = \
sg02ad('D', 'B', 'N', 'U', 'N', 'N', sort, 'R', n, m, 0, A, E, B, Q, R, S)
except ValueError as ve:
if ve.info < 0 or ve.info > 7:
e = ValueError(ve.message)
Expand Down
32 changes: 32 additions & 0 deletionscontrol/tests/statefbk_test.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
from control.statefbk import ctrb, obsv, place, place_varga, lqr, gram, acker
from control.matlab import *
from control.exception import slycot_check, ControlDimension
from control.mateqn import care, dare

class TestStatefbk(unittest.TestCase):
"""Test state feedback functions"""
Expand DownExpand Up@@ -298,6 +299,37 @@ def test_LQR_3args(self):
K, S, poles = lqr(sys, Q, R)
self.check_LQR(K, S, poles, Q, R)

@unittest.skipIf(not slycot_check(), "slycot not installed")
def test_care(self):
#unit test for stabilizing and anti-stabilizing feedbacks
#continuous-time

A = np.diag([1,-1])
B = np.identity(2)
Q = np.identity(2)
R = np.identity(2)
S = 0 * B
E = np.identity(2)
X, L , G = care(A, B, Q, R, S, E, stabilizing=True)
assert np.all(np.real(L) < 0)
X, L , G = care(A, B, Q, R, S, E, stabilizing=False)
assert np.all(np.real(L) > 0)

@unittest.skipIf(not slycot_check(), "slycot not installed")
def test_dare(self):
#discrete-time
A = np.diag([0.5,2])
B = np.identity(2)
Q = np.identity(2)
R = np.identity(2)
S = 0 * B
E = np.identity(2)
X, L , G = dare(A, B, Q, R, S, E, stabilizing=True)
assert np.all(np.abs(L) < 1)
X, L , G = dare(A, B, Q, R, S, E, stabilizing=False)
assert np.all(np.abs(L) > 1)


def test_suite():
return unittest.TestLoader().loadTestsFromTestCase(TestStatefbk)

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp