%
% PIDSAT.tex
%

\documentclass{beamer}

\usepackage{beamerthemeshadow}
\usepackage{listings}
\usepackage{graphics}
\usepackage{times}
\usepackage{algorithm2e}

\usepackage{pgf,pgfarrows,pgfnodes,pgfautomata,pgfheaps,pgfshade}
% \usepackage{amsmath,amssymb} \usepackage[latin1]{inputenc}
% \usepackage{colortbl}
\usepackage[english]{babel}

\newcommand{\erlang}{
\lstset{language=Prolog, basicstyle=\ttfamily\footnotesize,frame=trBL,
  frameround=fttt}}

\newcommand{\erlangsmall}{
\lstset{language=Prolog, basicstyle=\ttfamily\scriptsize,frame=trBL,
  frameround=fttt}}

\newcommand{\clang}{
\lstset{language=Prolog, basicstyle=\ttfamily\footnotesize,frame=trBL,
  frameround=fttt}}

\newcommand{\clangsmall}{
\lstset{language=Prolog, basicstyle=\ttfamily\scriptsize,frame=trBL,
  frameround=fttt}}

\newcommand{\clangtiny}{
\lstset{language=Prolog, basicstyle=\ttfamily\tiny,frame=trBL,
  frameround=fttt}}

\erlang

\newcommand\blue{\color[rgb]{0,0,1}}
\newcommand\green{\color[rgb]{0,0.5,0}}
\newcommand\red{\color[rgb]{1,0,0}}
\newcommand\black{\color[rgb]{0,0,0}}

\newcommand\tape[9]{
\framebox{#1}
\framebox{#2}
\framebox{#3}
\framebox{#4}
\framebox{#5}
\framebox{#6}
\framebox{#7}
\framebox{#8}
\framebox{#9}}

\newcommand\two[2]{
\framebox{#1}
\framebox{#2}}

\newcommand\six[6]{
\framebox{#1}
\framebox{#2}
\framebox{#3}
\framebox{#4}
\framebox{#5}
\framebox{#6}}

\newcommand\three[3]{
\framebox{#1}
\framebox{#2}
\framebox{#3}}

\title[Controllo PID con saturazione]{Controllo PID con saturazione}
%%

\author[Corrado Santoro]
       {Corrado Santoro}

\date{ }

\institute[University of Catania]
  {
    \begin{center}
      \textbf{\red{}ARSLAB - Autonomous and Robotic Systems Laboratory}\\
      Dipartimento di Matematica e Informatica - Universit\`{a} di Catania, Italy\\
      \texttt{santoro@dmi.unict.it}\\
      \includegraphics[width=60pt]{robotEscher_Eura_blur.eps}\\%%~~~~\includegraphics[width=80pt]{logo_dmi.png}
      Programmazione Sistemi Robotici\\
    \end{center}
  }



\begin{document}

\frame{\titlepage}




%%
\begin{frame}[fragile]
%%
  \frametitle{Schema controllo PID di un motore in CC}
%%
\begin{itemize}
%%
\item\footnotesize{}Il sistema complessivo per il controllo di un motore in
  CC \`{e} il seguente, ed include
%%
  \begin{itemize}
    \item\footnotesize{}L'algoritmo del PID (software)
    \item L'intefaccia PWM pi\`{u} il ponte-H (hardware)
    \item Il sistema motore + encoder (sistema fisico)
    \item L'intefaccia QEI (hardware)
  \end{itemize}
%%
\end{itemize}
%%
\begin{center}
\includegraphics[scale=0.2]{pid_pwm_encoder.eps}
\end{center}
%%
\end{frame}
%%




%%
\begin{frame}[fragile]
%%
  \frametitle{Limite del PWM}
%%
\begin{center}
\includegraphics[scale=0.15]{pid_pwm_encoder.eps}
\end{center}
%%
\begin{itemize}
%%
\item\footnotesize{}Ogni sistema fisico ha un \textbf{\red{}limite} oltre
  il quale non si pu\`{o} andare
%%
\item Nel caso del motore in CC tale limite \`{e} rappresentato dalla sua
  coppia e velocit\`{a}, che si ottengono quando il motore
  \`{e} alimentato alla sua tensione massima
%%
\item La tensione massima corrisponde al valore massimo che possiamo
  fornire al circuito PWM
\end{itemize}
%%
%%
\end{frame}





%%
\begin{frame}[fragile]
%%
  \frametitle{Limite del PWM}
%%
\begin{center}
\includegraphics[scale=0.15]{pid_pwm_encoder.eps}
\end{center}
%%
\begin{itemize}
%%
\item\footnotesize{}Il circuito generatore di PWM ``accetta''
  valori nell'intervallo $[-MAX, MAX]$
%%
\item Tuttavia, l'output del PID pu\`{o} essere \emph{qualunque numero} (il
  PID implementa una formula matematica)
%%
\item Pertanto \`{e} necessario \textbf{limitare} cio\`{e}
  \textbf{\red{}saturare} l'uscita del PID in modo che non vada oltre i
  limiti accettati dal circuito PWM
\end{itemize}
%%
%%
\end{frame}


%%
\begin{frame}[fragile]
%%
  \frametitle{Saturazione}
%%
\begin{center}
\includegraphics[scale=0.3]{saturatore.eps}
\end{center}
%%
\begin{itemize}
%%
\item\footnotesize{}Un blocco \textbf{\red{}saturatore} \`{e} rappresentato
  con il grafico \emph{in/out} mostrato in figura
%%
\item Quando $\red{}-MAX \le in \le MAX$, l'uscita ``ricopia'' l'ingresso
%%
\item Quando $\red{}in < -MAX$ (risp. $\red{}in > MAX$), l'uscita vale
  $\red{}-MAX$ (risp. $\red{}MAX$)
%%
\item Questo si traduce nel seguente codice:
\end{itemize}
%%
\black\clangtiny%%
\begin{lstlisting}
...
if (in < -MAX) out = -MAX;
else if (in > MAX) out = MAX;
else out = in;
...
\end{lstlisting}
%%
\end{frame}





%%
\begin{frame}[fragile]
%%
  \frametitle{PID con saturazione}
%%
\begin{center}
\includegraphics[scale=0.2]{pid_sat_pwm_encoder.eps}
\end{center}
%%
\begin{itemize}
%%
\item\footnotesize{}Il sistema completo \`{e} mostrato in figura
%%
\item Il codice del saturatore di solito \`{e} implementato all'interno
  della funzione del PID
%%
\end{itemize}
%%
%%
\end{frame}






%%
\begin{frame}[fragile]
%%
  \frametitle{Esempio di PID con saturazione}
%%
\begin{center}
\includegraphics[scale=0.2]{massa_attrito_pid.eps}
\end{center}
%%
\begin{itemize}
%%
\item\footnotesize{}Supponiamo il classico esempio di controllo (simulato)
  di massa su piano con attrito
%%
\item Consideriamo che l'output del PID (forza di spinta della massa) sia saturato ad un valore che non
  pu\`{o} superare i 10N
%%
\end{itemize}
%%
%%
\end{frame}



%%
\begin{frame}[fragile]
%%
  \frametitle{Codice del PID con saturazione (header file)}
%%
%%
\begin{itemize}
%%
\item\footnotesize{}Il codice del PID con saturazione diventa il seguente
\end{itemize}
%%
\black\clangtiny%%
\begin{lstlisting}
/*
 * pid_saturation.h
 */
#include "dynamic_system.h"
#include <stdbool.h>

class PID_Saturation : public DynamicSystem {

public:
    PID_Saturation(float kp, float ki, float kd, float saturation, float delta_t);
    float evaluate(float input);

private:
    float m_kp, m_ki, m_kd, m_saturation, m_out_i, m_prev_input;
    bool m_saturation_flag;
};
\end{lstlisting}
%%
\end{frame}


%%
\begin{frame}[fragile]
%%
  \frametitle{Codice del PID con saturazione (source file)}
%%
%%
\begin{itemize}
%%
\item\footnotesize{}Il codice del PID con saturazione diventa il seguente
\end{itemize}
%%
\black\clangtiny%%
\begin{lstlisting}
/*
 * pid_saturation.cpp
 */
#include "pid_saturation.h"

PID_Saturation::PID_Saturation(float kp, float ki, float kd,
                               float saturation, float delta_t)
    : DynamicSystem(delta_t), m_kp(kp), m_ki(ki), m_kd(kd),
      m_saturation(saturation), m_out_i(0), m_prev_input(0), m_saturation_flag(false)
{ }

float PID_Saturation::evaluate(float input)
{
    float deriv = (input - m_prev_input) / m_delta_t;
    m_prev_input = input;

    m_out_i = m_out_i + m_ki * input * m_delta_t;

    float output = input * m_kp + m_out_i + deriv * m_kd;

    if (output > m_saturation) {
        output = m_saturation;
    }
    else if (output < - m_saturation) {
        output = - m_saturation;
    }

    return output;
}
\end{lstlisting}
%%
\end{frame}


%%
\begin{frame}[fragile]
%%
  \frametitle{Risposta del sistema SENZA saturazione}
%%
%%
\begin{center}
\red{}$v_{target} = 8 m/s$\\
\red{}$K_p = 6$, $K_i = 3$, $K_d = 0$\\
\includegraphics[scale=0.3]{massa_pid.eps}
\end{center}
%%
\end{frame}


%%
\begin{frame}[fragile]
%%
  \frametitle{Risposta del sistema CON saturazione}
%%
%%
\begin{center}
\red{}$v_{target} = 8 m/s, sat = 10N$\\
\red{}$K_p = 6$, $K_i = 3$, $K_d = 0$\\
\includegraphics[scale=0.3]{risposta_pid_sat.eps}
\end{center}
%%
\begin{itemize}
\item\footnotesize{}E' comparsa una \textbf{brutta sovraelongazione} (detta
  \textbf{windup})
\item Il sistema \`{e} diventato pi\`{u} lento
\end{itemize}
\end{frame}




%%
\begin{frame}[fragile]
%%
  \frametitle{Uscita del PID CON saturazione}
%%
%%
\begin{center}
\red{}$v_{target} = 8 m/s, sat = 10N$\\
\red{}$K_p = 6$, $K_i = 3$, $K_d = 0$\\
\includegraphics[scale=0.3]{output_pid_sat.eps}
\end{center}
%%
\begin{itemize}
\item\footnotesize{}Durante il primo secondo di tempo, il sistema \`{e} \textbf{saturato}
\end{itemize}
\end{frame}


%%
\begin{frame}[fragile]
%%
  \frametitle{Saturazione e ottimizzazione anti-windup}
%%
\begin{itemize}
%%
\item\footnotesize{}Quando il sistema \`{e} saturato, l'errore non
  potr\`{a} mai ridursi secondo quanto ci si aspetta
%%
\item Cio\`{e} $e_{sat}(t) > e_{nonsat}(t)$, l'errore in saturazione \`{e}
  sempre pi\`{u} grande dell'errore quando non c'\`{e} la saturazione
%%
\item Poich\`{e} l'integratore \textbf{accumula} l'errore, quando siamo in
  saturazione \`{e} \textbf{inutile} accumulare errore che \textbf{non
    potr\`{a} ridursi}
%%
\item Per tale motivo, in \emph{codizioni di saturazione}, si preferisce
  \textbf{\red{}non calcolare il termine integrale}
%%
\item Tale ottimizzazione \`{e} detta \textbf{\red{}anti-windup}
\end{itemize}
%%
\end{frame}






%%
\begin{frame}[fragile]
%%
  \frametitle{Codice del PID con saturazione e anti-windup}
%%
%%
\black\clangtiny%%
\begin{lstlisting}
#define USE_ANTI_WIND_UP /* define or comment this to enable/disable anti-wind-up */

float PID_Saturation::evaluate(float input)
{
    float deriv = (input - m_prev_input) / m_delta_t;
    m_prev_input = input;

#ifdef USE_ANTI_WIND_UP
    /* if ANTIWINDUP is active, do not integrate when the system is in
        saturation */
    if (!m_saturation_flag)
        m_out_i = m_out_i + m_ki * input * m_delta_t;
#else
    m_out_i = m_out_i + m_ki * input * m_delta_t;
#endif

    float output = input * m_kp + m_out_i + deriv * m_kd;

    if (output > m_saturation) {
        output = m_saturation;
        m_saturation_flag = true;
    }
    else if (output < - m_saturation) {
        output = - m_saturation;
        m_saturation_flag = true;
    }
    else
        m_saturation_flag = false;

    return output;
}
\end{lstlisting}
%%
\end{frame}



%%
\begin{frame}[fragile]
%%
  \frametitle{Risposta del sistema CON saturazione e ANTI-WINDUP}
%%
%%
\begin{center}
\red{}$v_{target} = 8 m/s, sat = 10N$\\
\red{}$K_p = 6$, $K_i = 3$, $K_d = 0$\\
\includegraphics[scale=0.3]{risposta_pid_sat_anti.eps}
\end{center}
%%
\begin{itemize}
\item\footnotesize{}Con l'anti-windup \`{e} scomparsa la sovraelongazione
\end{itemize}
\end{frame}








%%
\frame{\titlepage}
%%


\end{document}
%%
%%

