From 5270b272c6d0e24f5161895131c95865a6e74996 Mon Sep 17 00:00:00 2001 From: jmaceiras <jeremy.maceiras@idiap.ch> Date: Wed, 11 May 2022 14:59:23 +0200 Subject: [PATCH] [matlab] Added LQR_infHor example --- matlab/LQR_infHor.m | 175 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 matlab/LQR_infHor.m diff --git a/matlab/LQR_infHor.m b/matlab/LQR_infHor.m new file mode 100644 index 0000000..4468647 --- /dev/null +++ b/matlab/LQR_infHor.m @@ -0,0 +1,175 @@ +%% Point-mass LQR with infinite horizon +%% +%% Copyright (c) 2021 Idiap Research Institute, http://www.idiap.ch/ +%% Written by Sylvain Calinon <https://calinon.ch> +%% +%% This file is part of RCFS. +%% +%% RCFS is free software: you can redistribute it and/or modify +%% it under the terms of the GNU General Public License version 3 as +%% published by the Free Software Foundation. +%% +%% RCFS is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with RCFS. If not, see <http://www.gnu.org/licenses/>. + + +function LQR_infHor + +%% Parameters +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +param.nbData = 200; %Number of datapoints +param.nbRepros = 4; %Number of reproductions + +param.param.nbVarPos = 2; %Dimension of position data (here: x1,x2) +param.nbDeriv = 2; %Number of static & dynamic features (D=2 for [x,dx]) +param.nbVar = param.param.nbVarPos * param.nbDeriv; %Dimension of state vector in the tangent space +param.dt = 1E-2; %Time step duration +param.rfactor = 4E-2; %Control cost in LQR + +%Control cost matrix +R = eye(param.param.nbVarPos) * param.rfactor; + +%Target and desired covariance +param.Mu = [randn(param.param.nbVarPos,1); zeros(param.param.nbVarPos*(param.nbDeriv-1),1)]; + +[Ar,~] = qr(randn(param.param.nbVarPos)); +xCov = Ar * diag(rand(param.param.nbVarPos,1)) * Ar' * 1E-1 + +%% Discrete dynamical System settings +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +A1d = zeros(param.nbDeriv); +for i=0:param.nbDeriv-1 + A1d = A1d + diag(ones(param.nbDeriv-i,1),i) * param.dt^i * 1/factorial(i); %Discrete 1D +end +B1d = zeros(param.nbDeriv,1); +for i=1:param.nbDeriv + B1d(param.nbDeriv-i+1) = param.dt^i * 1/factorial(i); %Discrete 1D +end +A = kron(A1d, eye(param.param.nbVarPos)); %Discrete nD +B = kron(B1d, eye(param.param.nbVarPos)); %Discrete nD + + +%% discrete LQR with infinite horizon +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Q = blkdiag(inv(xCov), zeros(param.param.nbVarPos*(param.nbDeriv-1))); %Precision matrix +P = solveAlgebraicRiccati_eig_discrete(A, B*(R\B'), (Q+Q')/2); +L = (B' * P * B + R) \ B' * P * A; %Feedback gain (discrete version) + +%Test ratio between kp and kv +if param.nbDeriv>1 + kp = eigs(L(:,1:param.param.nbVarPos)); + kv = eigs(L(:,param.param.nbVarPos+1:end)); + ratio = kv ./ (2 * kp.^.5) +end + +for n=1:param.nbRepros + x = [ones(param.param.nbVarPos,1)+randn(param.param.nbVarPos,1)*5E-1; zeros(param.param.nbVarPos*(param.nbDeriv-1),1)]; + for t=1:param.nbData + r(n).Data(:,t) = x; + u = L * (param.Mu - x); %Compute acceleration (with only feedback terms) + x = A * x + B * u; + end +end + + +%% Plots +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +figure('position',[10,10,650,650]); hold on; axis off; grid off; +plotGMM(param.Mu(1:2), xCov(1:2,1:2), [.8 0 0], .3); +for n=1:param.nbRepros + plot(r(n).Data(1,:), r(n).Data(2,:), '-','linewidth',1,'color',[0 0 0]); +end +%plot(param.Mu(1,1), param.Mu(2,1), 'r.','markersize',80); +axis equal; +%print('-dpng','graphs/demo_MPC_infHor01.png'); + + +%% Timeline plot +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +labList = {'x_1','x_2','dx_1','dx_2','ddx_1','ddx_2'}; +figure('position',[720 10 600 650],'color',[1 1 1]); +for j=1:param.nbVar +subplot(param.nbVar+1,1,j); hold on; +for n=1:param.nbRepros + plot(r(n).Data(j,:), '-','linewidth',1,'color',[0 0 0]); +end +if j<7 + ylabel(labList{j},'fontsize',14,'interpreter','latex'); +end +end +%Speed profile +if param.nbDeriv>1 +subplot(param.nbVar+1,1,param.nbVar+1); hold on; +for n=1:param.nbRepros + sp = sqrt(r(n).Data(3,:).^2 + r(n).Data(4,:).^2); + plot(sp, '-','linewidth',1,'color',[0 0 0]); +end +ylabel('|dx|','fontsize',14); +xlabel('t','fontsize',14); +end +%print('-dpng','graphs/demo_LQR_infHor01.png'); + +pause; +close all; +end + +%%%%%%%%%%%%%%%%%%%%%% +% Solve Algebraic Ricatty discrete equation +function X = solveAlgebraicRiccati_eig_discrete(A, G, Q) + n = size(A,1); + + %Symplectic matrix (see https://en.wikipedia.org/wiki/Algebraic_Riccati_equation) + %Z = [A+B*(R\B')/A'*Q, -B*(R\B')/A'; -A'\Q, A'^-1]; + Z = [A+G/A'*Q, -G/A'; -A'\Q, inv(A')]; + + + %Since Z is symplectic, if it does not have any eigenvalues on the unit circle, + %then exactly half of its eigenvalues are inside the unit circle. + [V,D] = eig(Z); + U = []; + for j=1:2*n + if norm(D(j,j)) < 1 %inside unit circle + U = [U V(:,j)]; + end + end + + X = real(U(n+1:end,:) / U(1:n,:)); +end + +%%%%%%%%%%%%%%%%%%%%%% +% Plot a 2D Mixture of Gaussians +function [h, X] = plotGMM(Mu, Sigma, color, valAlpha) + nbStates = size(Mu,2); + nbDrawingSeg = 100; + darkcolor = color * .7; %max(color-0.5,0); + t = linspace(-pi, pi, nbDrawingSeg); + if nargin<4 + valAlpha = 1; + end + + h = []; + X = zeros(2,nbDrawingSeg,nbStates); + for i=1:nbStates + [V,D] = eig(Sigma(:,:,i)); + R = real(V*D.^.5); + X(:,:,i) = R * [cos(t); sin(t)] + repmat(Mu(:,i), 1, nbDrawingSeg); + if nargin>3 %Plot with alpha transparency + h = [h patch(X(1,:,i), X(2,:,i), color, 'lineWidth', 1, 'EdgeColor', color, 'facealpha', valAlpha,'edgealpha', valAlpha)]; + h = [h plot(Mu(1,:), Mu(2,:), '.', 'markersize', 10, 'color', darkcolor)]; + else %Plot without transparency + h = [h patch(X(1,:,i), X(2,:,i), color, 'lineWidth', 1, 'EdgeColor', darkcolor)]; + h = [h plot(Mu(1,:), Mu(2,:), '.', 'markersize', 10, 'color', darkcolor)]; + end + end +end + + + -- GitLab