diff --git a/doc/rcfs.pdf b/doc/rcfs.pdf index 3549eb61368a91f8e27655b1186a4893bd7c65e8..5ac075e3c1a39d5ff18711888db9c7c1ce28d244 100644 Binary files a/doc/rcfs.pdf and b/doc/rcfs.pdf differ diff --git a/doc/rcfs.tex b/doc/rcfs.tex index a8af112019c488a5363655f4102bdff6679ab0ee..2c1ab34625f65dca04d9a350e54c9180b2bbecf7 100644 --- a/doc/rcfs.tex +++ b/doc/rcfs.tex @@ -2,6 +2,7 @@ \documentclass[10pt,a4paper]{article} %twocolumn \usepackage{graphicx,amsmath,amssymb,bm,xcolor,soul,nicefrac,listings,algorithm2e,dsfont,caption,subcaption,wrapfig,sidecap} \usepackage[hidelinks]{hyperref} +\usepackage[makeroom]{cancel} %pseudocode \newcommand\mycommfont[1]{\footnotesize\ttfamily\textcolor{lightgray}{#1}} @@ -343,7 +344,7 @@ where $\bm{J}_{\bm{r}}\in\mathbb{R}^{R\times D}$ is the Jacobian matrix of $\bm{ The update rule in \eqref{eq:Taylor_nD_update} then becomes \begin{align} \bm{x}_{k+1} &= \bm{x}_k - {\big(\bm{J}_{\bm{r}}^\trsp(\bm{x}_k) \bm{J}_{\bm{r}}(\bm{x}_k)\big)}^{-1} \, - \bm{J}_{\bm{r}}^\trsp(\bm{x}_k) \, \bm{r}(\bm{x}_k) \\ + \bm{J}_{\bm{r}}^\trsp(\bm{x}_k) \, \bm{r}(\bm{x}_k) \nonumber\\ &= \bm{x}_k - \bm{J}_{\bm{r}}^\psin(\bm{x}_k) \, \bm{r}(\bm{x}_k), \label{eq:GaussNewtonUpdate} \end{align} @@ -356,16 +357,62 @@ The Gauss--Newton algorithm is the workhorse of many robotics problems, includin \subsection{Least squares}\label{sec:LS} When the cost $c(\bm{x})$ is a quadratic function w.r.t.\ $\bm{x}$, the optimization problem can be solved directly, without requiring iterative steps. Indeed, for any matrix $\bm{A}$ and vector $\bm{b}$, we can see that if -\begin{equation*} - c(\bm{x}) = (\bm{A}\bm{x}-\bm{b})^\trsp (\bm{A}\bm{x}-\bm{b}), -\end{equation*} -derivating $c(\bm{x})$ w.r.t.\ $\bm{x}$ and equating to zero yields -\begin{equation*} +\begin{equation} + c(\bm{x}) = \|\bm{A}\bm{x}-\bm{b}\|^2 = (\bm{A}\bm{x}-\bm{b})^\trsp (\bm{A}\bm{x}-\bm{b}), + \label{eq:costquadratic} +\end{equation} +deriving $c(\bm{x})$ w.r.t.\ $\bm{x}$ and equating to zero yields +\begin{equation} \bm{A}\bm{x} - \bm{b} = \bm{0} - \iff \bm{x} = \bm{A}^\psin\bm{b}, -\end{equation*} + \iff \bm{x} = (\bm{A}^\trsp \bm{A})^{-1} \bm{A}^\trsp \bm{b} = \bm{A}^\psin \bm{b}, + \label{eq:costquadraticsolution} +\end{equation} which corresponds to the standard analytic least squares estimate. We will see later in the inverse kinematics section that for the complete solution can also include a nullspace structure. +In contrast to the Gauss--Newton algorithm presented in Section \ref{sec:GaussNewton}, the optimization problem in \eqref{eq:costquadratic}, described by a quadratic cost on the decision variable $\bm{x}$, admits the solution \eqref{eq:costquadraticsolution} that can be computed directly without relying on an iterative procedure. We can observe that if we follow the Gauss--Newton procedure, the residual vector corresponding to the cost \eqref{eq:costquadratic} is $\bm{r}=\bm{A}\bm{x}-\bm{b}$ and its Jacobian matrix is $\bm{J}_{\bm{r}}=\bm{A}$. By starting from an initial estimate $\bm{x}_0$, the Gauss--Newton update in \eqref{eq:GaussNewtonUpdate} then takes the form +\begin{align*} + \bm{x}_{k+1} &= \bm{x}_k - \bm{A}^\psin (\bm{A}\bm{x}_k-\bm{b})\\ + &= \bm{x}_k - (\bm{A}^\trsp \bm{A})^{-1} \bm{A}^\trsp (\bm{A}\bm{x}_k-\bm{b})\\ + &= \bm{x}_k - \cancel{(\bm{A}^\trsp \bm{A})^{-1}} \cancel{(\bm{A}^\trsp\bm{A})} \bm{x}_k + \bm{A}^\psin \bm{b}\\ + &= \bm{A}^\psin \bm{b}, +\end{align*} +which converges in a single iteration, independently of the initial guess $\bm{x}_0$. Indeed, a cost that takes a quadratic form with respect to the decision variable can be soled in batch form (least squares solution), which will be a useful property that we will exploit later in the context of linear quadratic controllers. + +A ridge regression problem can similarly be defined as +\begin{align} + \bm{\hat{x}} &= \arg\min_{\bm{x}} \; \|\bm{A}\bm{x}-\bm{b})\|^2 + \alpha \|\bm{x}\|^2 \nonumber\\ + &= (\bm{A}^\trsp \bm{A} + \alpha\bm{I})^{-1} \bm{A}^\trsp \bm{b}, \label{eq:regLS} +\end{align} +which is also called penalized least squares, robust regression, damped least squares or Tikhonov regularization. In \eqref{eq:regLS}, $\bm{I}$ denotes an identity matrix (diagonal matrix with 1 as elements in the diagonal). $\alpha$ is typically a small scalar value acting as a regularization term when inverting the matrix $\bm{A}^\trsp \bm{A}$. + +The cost can also be weighted by a matrix $\bm{W}$, providing the weighted least squares solution +\begin{align} + \bm{\hat{x}} &= \arg\min_{\bm{x}} \; \|\bm{A}\bm{x}-\bm{b}\|^2_{\bm{W}} \nonumber\\ + &= \arg\min_{\bm{x}} \; (\bm{A}\bm{x}-\bm{b})^\trsp \bm{W} (\bm{A}\bm{x}-\bm{b}) \nonumber\\ + &= (\bm{A}^\trsp \bm{W} \bm{A})^{-1} \bm{A}^\trsp \bm{W} \bm{b}. \label{eq:WLS} +\end{align} + +By combining \eqref{eq:regLS} and \eqref{eq:WLS}, a weighted ridge regression problem can be defined as +\begin{align} + \bm{\hat{x}} &= \arg\min_{\bm{x}} \; \|\bm{A}\bm{x}-\bm{b}\|^2_{\bm{W}} + \alpha \|\bm{x}\|^2 \nonumber\\ + &= (\bm{A}^\trsp \bm{W} \bm{A} + \alpha\bm{I})^{-1} \bm{A}^\trsp \bm{W} \bm{b}. \label{eq:regWLS} +\end{align} + +If the matrices and vectors in \eqref{eq:regWLS} have the structure +\begin{equation*} + \bm{W}=\begin{bmatrix}\bm{W}_{1}&\bm{0}\\\bm{0}&\bm{W}_{2}\end{bmatrix},\quad + \bm{A}=\begin{bmatrix}\bm{A}_{1}\\\bm{A}_{2}\end{bmatrix},\quad + \bm{x}=\begin{bmatrix}\bm{x}_{1}\\\bm{x}_{2}\end{bmatrix},\quad + \bm{b}=\begin{bmatrix}\bm{b}_{1}\\\bm{b}_{2}\end{bmatrix}, +\end{equation*} +we could consider an optimization problem using only the first part of the matrices, which would yield the estimate +\begin{align} + \bm{\hat{x}} &= \arg\min_{\bm{x}} \; \|\bm{A}_1\bm{x}-\bm{b}_1\|^2_{\bm{W}_1} + \alpha \|\bm{x}\|^2 \nonumber\\ + &= (\bm{A}_1^\trsp \bm{W}_1 \bm{A}_1 + \alpha\bm{I})^{-1} \bm{A}_1^\trsp \bm{W}_1 \bm{b}_1. \label{eq:regWLS1} +\end{align} + +It is important to observe that the result in \eqref{eq:regWLS1} is not the same as that of computing \eqref{eq:regWLS} with $\bm{W}_2=\bm{0}$. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Least squares with constraints}\label{sec:LSconstraints} diff --git a/matlab/spline1D.m b/matlab/spline1D.m index f822cbeec5ea200b20317de732ccb295af01dc43..e20e2eee8c1487d2c81bb43c43f9819193567e41 100644 --- a/matlab/spline1D.m +++ b/matlab/spline1D.m @@ -15,7 +15,7 @@ param.nbFct = 4; %Number of basis functions (code valid for param.nbFct>2) param.nbSeg = 7; %Number of segments param.nbIn = 1; %Dimension of input data (here: time) param.nbOut = 1; %Dimension of position data (here: x) -param.nbDim = param.nbFct*param.nbSeg*20; %Number of datapoints in a trajectory +param.nbDim = param.nbFct*param.nbSeg*20+1; %Number of datapoints in a trajectory %% Load handwriting data @@ -70,7 +70,7 @@ end param.BC = param.B * param.C; %Time parameters matrix to compute positions -t = linspace(0, 1-1/param.nbDim, param.nbDim); +t = linspace(0, 1, param.nbDim); delta_t = t(2) - t(1); [Psi, dPsi, phi] = computePsiList(t, param); @@ -78,18 +78,18 @@ delta_t = t(2) - t(1); %% Trajectory encoding and reproduction as movement primitives %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Batch estimation of superposition weights from reference position profile -wb = Psi \ x0; +w = Psi \ x0; %%Batch estimation of superposition weights from reference position profile with additional cost on derivatives -%wb = (Psi'*Psi + dPsi'*dPsi*1E-3) \ Psi' * x0; +%w = (Psi'*Psi + dPsi'*dPsi*1E-3) \ Psi' * x0; -param.Mw = param.BC * wb; %Transformation matrix +param.Mw = param.BC * w; %Transformation matrix %Reconstruction of trajectories -xb = Psi * wb; -dxb = dPsi * wb; +x = Psi * w; +dx = dPsi * w; %Useful only for visualization -wb_vis = kron(param.C, eye(param.nbOut)) * wb; +w_vis = kron(param.C, eye(param.nbOut)) * w; %% Plots @@ -101,7 +101,7 @@ clrmap = lines(param.nbFct * param.nbSeg); %Colors for total number of control p %Plot reference subplot(3,2,1); hold on; title('Reference position profile (in red)'); plot(t, x0, 'linewidth',4,'color',[.8 .6 .6]); -plot(t, xb, 'linewidth',4,'color',[.6 .6 .6]); +plot(t, x, 'linewidth',4,'color',[.6 .6 .6]); xlabel('t','fontsize',30); ylabel('x','fontsize',30); set(gca,'xtick',[],'ytick',[]); @@ -109,7 +109,7 @@ set(gca,'xtick',[],'ytick',[]); %Plot derivatives subplot(3,2,2); hold on; title('Velocity profile'); plot(t(1:end-1), diff(x0)/delta_t, 'linewidth',8,'color',[.8 .6 .6]); -plot(t, dxb, 'linewidth',4,'color',[.6 .6 .6]); +plot(t, dx, 'linewidth',4,'color',[.6 .6 .6]); axis tight; xlabel('t','fontsize',30); ylabel('dx/dt','fontsize',30); @@ -117,21 +117,21 @@ set(gca,'xtick',[],'ytick',[]); subplot(3,2,3); hold on; title('Reconstructed position profile'); %Plot reconstructed signal -plot(t, xb, 'linewidth',4,'color',[.6 .6 .6]); +plot(t, x, 'linewidth',4,'color',[.6 .6 .6]); %Plot control points tSeg = []; for n=1:param.nbSeg tSeg_n = linspace(0, 1/param.nbSeg, param.nbFct) + (n-1)/param.nbSeg; tSeg = [tSeg, tSeg_n]; end -plot(tSeg, wb_vis, '.', 'markersize',38,'color',[0 0 0]); +plot(tSeg, w_vis, '.', 'markersize',38,'color',[0 0 0]); %Plot segments between control points for n=1:param.nbSeg id = (n-1)*param.nbFct + [1,2]; - plot(tSeg(id), wb_vis(id), '-', 'linewidth',2,'color',[0 0 0]); + plot(tSeg(id), w_vis(id), '-', 'linewidth',2,'color',[0 0 0]); id = n*param.nbFct + [-1,0]; - plot(tSeg(id), wb_vis(id), '-', 'linewidth',2,'color',[0 0 0]); - plot([tSeg(id(2)), tSeg(id(2))], [min(wb)-2, max(wb)+2], '-', 'linewidth',2,'color',[.8 .8 .8]); + plot(tSeg(id), w_vis(id), '-', 'linewidth',2,'color',[0 0 0]); + plot([tSeg(id(2)), tSeg(id(2))], [min(w)-2, max(w)+2], '-', 'linewidth',2,'color',[.8 .8 .8]); end axis tight; xlabel('t','fontsize',30); @@ -140,12 +140,12 @@ set(gca,'xtick',[],'ytick',[]); %Plot reconstructed derivatives subplot(3,2,4); hold on; title('Reconstructed velocity profile'); -plot(t, dxb,'linewidth',4,'color',[.6 .6 .6]); -%plot(t(1:end-1), diff(xb)/delta_t, ':','linewidth',4,'color',[.2 .2 .2]); +plot(t, dx,'linewidth',4,'color',[.6 .6 .6]); +%plot(t(1:end-1), diff(x)/delta_t, ':','linewidth',4,'color',[.2 .2 .2]); %Plot segments between control points for n=1:param.nbSeg id = n*param.nbFct + [-1,0]; - plot([tSeg(id(2)), tSeg(id(2))], [min(dxb)-2, max(dxb)+2], '-', 'linewidth',2,'color',[.8 .8 .8]); + plot([tSeg(id(2)), tSeg(id(2))], [min(dx)-2, max(dx)+2], '-', 'linewidth',2,'color',[.8 .8 .8]); end axis tight; xlabel('t','fontsize',30);