Source code for rofunc.planning_control.lqt.lqt_fb

"""
    LQT computed in a recursive way (via-point example)

    Refers to https://gitlab.idiap.ch/rli/robotics-codes-from-scratch by Dr. Sylvain Calinon
"""
import matplotlib.pyplot as plt
import numpy as np
from omegaconf import DictConfig

import rofunc as rf
from rofunc.planning_control.lqt.lqt import LQT
from rofunc.utils.logger.beauty_logger import beauty_print


[docs]class LQTFb(LQT): def __init__(self, all_points, cfg: DictConfig = None): super().__init__(all_points, cfg)
[docs] def get_matrices(self): self.cfg.nbPoints = len(self.via_points) # Control cost matrix R = np.eye(self.cfg.nbVarPos) * self.cfg.rfactor # Sparse reference with a set of via-points tl = np.linspace(0, self.cfg.nbData - 1, self.cfg.nbPoints + 1) tl = np.rint(tl[1:]) # Definition of augmented precision matrix Qa based on standard precision matrix Q0 Q0 = np.diag(np.hstack([np.ones(self.cfg.nbVarPos), np.zeros(self.cfg.nbVar - self.cfg.nbVarPos)])) Q0_augmented = np.identity(self.cfg.nbVarX) Q0_augmented[:self.cfg.nbVar, :self.cfg.nbVar] = Q0 Q = np.zeros([self.cfg.nbVarX, self.cfg.nbVarX, self.cfg.nbData]) for i in range(self.cfg.nbPoints): Q[:, :, int(tl[i])] = np.vstack([ np.hstack([np.identity(self.cfg.nbVar), np.zeros([self.cfg.nbVar, 1])]), np.hstack([-self.via_points[i, :], 1])]) @ Q0_augmented @ np.vstack([ np.hstack([np.identity(self.cfg.nbVar), -self.via_points[i, :].reshape([-1, 1])]), np.hstack([np.zeros(self.cfg.nbVar), 1])]) return Q, R, tl
[docs] def set_dynamical_system(self): A1d = np.zeros((self.cfg.nbDeriv, self.cfg.nbDeriv)) for i in range(self.cfg.nbDeriv): A1d += np.diag(np.ones((self.cfg.nbDeriv - i,)), i) * self.cfg.dt ** i / np.math.factorial(i) # Discrete 1D B1d = np.zeros((self.cfg.nbDeriv, 1)) for i in range(0, self.cfg.nbDeriv): B1d[self.cfg.nbDeriv - i - 1, :] = self.cfg.dt ** (i + 1) * 1 / np.math.factorial(i + 1) # Discrete 1D A0 = np.kron(A1d, np.eye(self.cfg.nbVarPos)) # Discrete nD B0 = np.kron(B1d, np.eye(self.cfg.nbVarPos)) # Discrete nD A = np.eye(A0.shape[0] + 1) # Augmented A A[:A0.shape[0], :A0.shape[1]] = A0 B = np.vstack((B0, np.zeros((1, self.cfg.nbVarPos)))) # Augmented B return A, B
[docs] def get_u_x(self, P: np.ndarray, R: np.ndarray, A: np.ndarray, B: np.ndarray, state_noise: np.ndarray): x_hat = np.zeros((self.cfg.nbVarX, 2, self.cfg.nbData)) u_hat = np.zeros((self.cfg.nbVarPos, 2, self.cfg.nbData)) for n in range(2): x = np.hstack([np.zeros(self.cfg.nbVar), 1]) for t in range(self.cfg.nbData): Z_bar = B.T @ P[:, :, t] @ B + R K = np.linalg.inv(Z_bar.T @ Z_bar) @ Z_bar.T @ B.T @ P[:, :, t] @ A # Feedback gain u = -K @ x # Acceleration command with FB on augmented state (resulting in feedback and feedforward terms) x = A @ x + B @ u # Update of state vector if t == 25 and n == 1: x += state_noise if t == 70 and n == 1: x += state_noise if t == 75 and n == 1: x += state_noise x_hat[:, n, t] = x # Log data u_hat[:, n, t] = u # Log data return u_hat, x_hat
[docs] def solve(self, state_noise, for_test=False): beauty_print('LQT with feedback control', type='module') Q, R, tl = self.get_matrices() A, B = self.set_dynamical_system() P = np.zeros((self.cfg.nbVarX, self.cfg.nbVarX, self.cfg.nbData)) P[:, :, -1] = Q[:, :, -1] for t in range(self.cfg.nbData - 2, -1, -1): P[:, :, t] = Q[:, :, t] - A.T @ ( P[:, :, t + 1] @ np.dot(B, np.linalg.pinv(B.T @ P[:, :, t + 1] @ B + R))
[docs] @ B.T @ P[:, :, t + 1] - P[:, :, t + 1]) @ A u_hat, x_hat = self.get_u_x(P, R, A, B, state_noise) self.vis3d(x_hat, for_test=for_test) return u_hat, x_hat
def vis(self, x_hat, for_test): plt.figure() for n in range(2): plt.plot(x_hat[0, n, :], x_hat[1, n, :], label="Trajectory {}".format(n + 1)) plt.scatter(x_hat[0, n, 0], x_hat[1, n, 0], marker='o') plt.scatter(self.via_points[:, 0], self.via_points[:, 1], s=20 * 1.5 ** 2, marker='o', color="red", label="Via-points") plt.legend() if not for_test: plt.show()
[docs] def vis3d(self, x_hat, for_test): fig = plt.figure(figsize=(4, 4)) ax = fig.add_subplot(111, projection='3d', fc='white') rf.visualab.traj_plot([x_hat.transpose(1, 2, 0)[0]], mode='3d', ori=False, g_ax=ax, legend='Trajectory 1') rf.visualab.traj_plot([x_hat.transpose(1, 2, 0)[1]], mode='3d', ori=False, g_ax=ax, legend='Trajectory 2') ax.scatter(self.via_points[:, 0], self.via_points[:, 1], self.via_points[:, 2], s=20 * 1.5 ** 2, marker='o', color="red", label="Via-points") plt.legend() if not for_test: plt.show()