.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/sp_lqr.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_sp_lqr.py: Discrete Time LQR ================= .. GENERATED FROM PYTHON SOURCE LINES 5-26 .. code-block:: Python import numpy as np from _sgm_test_util import LTI_plot from matplotlib import pyplot as plt import condor as co class DblIntSampled(co.ODESystem): A = np.array([[0.0, 1.0], [0.0, 0.0]]) B = np.array([[0.0], [1.0]]) K = parameter(shape=(1, B.shape[0])) dt = parameter() x = state(shape=A.shape[0]) u = state(shape=B.shape[1]) dot[x] = A @ x + B @ u .. GENERATED FROM PYTHON SOURCE LINES 27-30 To implement the periodic sampling, we use an event with :attr:`~condor.contrib.Event.at_time` with a slice specification, starting at time 0 and occurring every ``dt`` time units without end. .. GENERATED FROM PYTHON SOURCE LINES 30-38 .. code-block:: Python class SampleEvent(DblIntSampled.Event): at_time = slice(None, None, dt) update[u] = -K @ x .. GENERATED FROM PYTHON SOURCE LINES 39-40 Now declare the trajectory analysis to simulate .. GENERATED FROM PYTHON SOURCE LINES 40-65 .. code-block:: Python class DblIntSampledLQR(DblIntSampled.TrajectoryAnalysis): tf = 32.0 initial[x] = [1.0, 0.1] # can initialize for aesthetics, but zero-crossing at t=0 updates it initial[u] = -K @ initial[x] Q = np.eye(2) R = np.eye(1) cost = trajectory_output(integrand=(x.T @ Q @ x + u.T @ R @ u) / 2) class Options: adjoint_adaptive_max_step_size = False state_max_step_size = 0.5 / 8 adjoint_max_step_size = 0.5 / 8 dt = 0.5 sim = DblIntSampledLQR(K=[0.5, 0.5], dt=dt) LTI_plot(sim) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/images/sphx_glr_sp_lqr_001.png :alt: DblIntSampledLQR DblIntSampledLQRState.x :srcset: /examples/images/sphx_glr_sp_lqr_001.png :class: sphx-glr-multi-img * .. image-sg:: /examples/images/sphx_glr_sp_lqr_002.png :alt: DblIntSampledLQR DblIntSampledLQRState.u :srcset: /examples/images/sphx_glr_sp_lqr_002.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 66-68 Determine the optimal gain by embedding the trajectory analysis in an optimization problem: .. GENERATED FROM PYTHON SOURCE LINES 68-84 .. code-block:: Python class SampledOptLQR(co.OptimizationProblem): K = variable(shape=DblIntSampledLQR.K.shape) params = parameter.create_from(DblIntSampled.parameter, K=K) sim = DblIntSampledLQR(**params) objective = sim.cost class Options: __implementation__ = co.implementations.ScipyCG lqr_sol = SampledOptLQR(dt=dt) print(lqr_sol.K) .. rst-class:: sphx-glr-script-out .. code-block:: none /opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/condor/implementations/iterative.py:481: RuntimeWarning: Method CG cannot handle bounds. min_out = minimize( [[0.66131423 1.32662666]] .. GENERATED FROM PYTHON SOURCE LINES 85-86 Compare with the solution from the discrete algebraic Riccati equation: .. GENERATED FROM PYTHON SOURCE LINES 86-97 .. code-block:: Python from scipy import linalg, signal Ad, Bd, _, _, _ = signal.cont2discrete( (DblIntSampledLQR.A, DblIntSampledLQR.B, None, None), dt ) S = linalg.solve_discrete_are(Ad, Bd, DblIntSampledLQR.Q, DblIntSampledLQR.R) K = linalg.solve(Bd.T @ S @ Bd + DblIntSampledLQR.R, Bd.T @ S @ Ad) print(K) .. rst-class:: sphx-glr-script-out .. code-block:: none [[0.65140165 1.31420219]] .. GENERATED FROM PYTHON SOURCE LINES 98-102 .. code-block:: Python sim_are = DblIntSampledLQR(K=K, dt=dt) LTI_plot(sim_are) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/images/sphx_glr_sp_lqr_003.png :alt: DblIntSampledLQR DblIntSampledLQRState.x :srcset: /examples/images/sphx_glr_sp_lqr_003.png :class: sphx-glr-multi-img * .. image-sg:: /examples/images/sphx_glr_sp_lqr_004.png :alt: DblIntSampledLQR DblIntSampledLQRState.u :srcset: /examples/images/sphx_glr_sp_lqr_004.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 103-105 .. code-block:: Python plt.show() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 23.155 seconds) .. _sphx_glr_download_examples_sp_lqr.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: sp_lqr.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: sp_lqr.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: sp_lqr.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_