%$Header: /home/dashley/cvsrep/e3ft_gpl01/e3ft_gpl01/dtaipubs/esrgubka/c_dta0/c_dta0.tex,v 1.5 2003/03/03 23:50:43 dtashley Exp $ \chapter[\cdtazeroshorttitle{}]{\cdtazerolongtitle{}} \label{cdta0} \beginchapterquote{``Under construction!''} {Under construction!} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Introduction} %Section tag: INT0 \label{cdta0:sint0} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section[Fixed-Period Process Scheduling] {Load Balancing For Fixed-Period Process Scheduling Using Integer Counting} %Section tag: PSI0 \label{cdta0:spsi0} \index{process scheduling!using integer counting}It happens in a variety of contexts in small microcontroller work that one schedules processes (which may be implemented as subroutines or functions) with a fixed period using integer counting. Such scheduling tends to take the form of the code snippet in Figure \ref{fig:cdta0:spsi0:01}. Typically a ``master'' scheduling function is called at a periodic rate, and the scheduled functions are called once every $T_i$ invocations of the master scheduling function ($T_i$ is defined later). Note in the figure that every scheduled function is called with perfect periodicity, but that the invocation sequence can be staggered. Note also in the figure that the comments assume that the scheduling function is called every 10ms (which is typical in microcontroller work). \begin{figure} \begin{small} \begin{verbatim} /* The following "stagger" values are what we are attempting to ** analytically determine at compile-time so as to minimize the ** maximum CPU time used in the worst-case tick. */ #define P1_STAGGER (0) #define P2_STAGGER (0) #define P3_STAGGER (0) /* The periods are fixed and not subject to change. The periods ** are input to any compile-time algorithm employed. */ #define P1_PERIOD (2) /* Every 20ms. */ #define P2_PERIOD (5) /* Every 100ms. */ #define P3_PERIOD (100) /* Every 1000ms = 1 second. */ /* These are the integer counters. Their initial load values, which ** determine the staggering, are the parameters we seek to ** determine. */ static unsigned char p1_ctr = P1_STAGGER; static unsigned char p2_ctr = P2_STAGGER; static unsigned char p3_ctr = P3_STAGGER; /* This is the master scheduling function called every 10ms. It ** calls the periodic functions. Note that this is an integer ** counting problem. */ void master_scheduling_function(void) { p1_ctr++; if (p1_ctr >= P1_PERIOD) { Process_1(); /* Call the process. */ p1_ctr = 0; /* Reset the counter. */ } p2_ctr++; if (p2_ctr >= P2_PERIOD) { Process_2(); /* Call the process. */ p2_ctr = 0; /* Reset the counter. */ } p3_ctr++; if (p3_ctr >= P3_PERIOD) { Process_3(); /* Call the process. */ p3_ctr = 0; /* Reset the counter. */ } } \end{verbatim} \end{small} \caption{Code Snippet Illustrating Fixed-Period Integer Counter Process Scheduling (3 Processes)} \label{fig:cdta0:spsi0:01} \end{figure} It is easy to see from Figure \ref{fig:cdta0:spsi0:01} that it may happen on a single invocation of the master scheduling function that several or all of the processes are scheduled. If the scheduling of the processes is not staggered, this will happen for the first time on the invocation (or ``tick'') corresponding to the least common multiple of all of the periods. In the case of Figure \ref{fig:cdta0:spsi0:01}, $LCM(2,5,100) = 100$, and so on the hundredth invocation of the master scheduling function, all three processes will run. It may be undesirable to run all three processes on the same invocation of the master scheduling function, because this may require a large amount of CPU time. The general question to which we seek an answer is: \emph{How should the stagger values be chosen so as to minimize the maximum amount of CPU time taken on any invocation of the master scheduling function?} We denote the set of $N$ processes that we must schedule by $\{ P_1, P_2, \ldots , P_N \}$. Process $P_i$ has period $T_i$ (measured in invocations or ``ticks'' of the master scheduling function, or ``ticks''). Note that $T_i$ is dimensionless. Each process $P_i$ also has cost $\tau_i$ (the cost is usually the execution time of the function, but could in principle represent any property of interest). Note that there is no required relationship between $\{ T_i \}$ and $\{ \tau_i \}$, as we are not determining schedulability. Thus $\{ \tau_i \}$ may be specified in any time unit, or it may not represent time at all. We agree that each invocation of the master scheduling function is one ``tick'' in discrete time, and that the first invocation of the master scheduling function is denoted $t_1$ or $t=1$. With no staggering ($z_i = 0$) each process $P_i$ will run whenever \begin{equation} \label{eq:cdta0:spsi0:01} t \bmod T_i = 0 . \end{equation} We may modify the invocation sequence of a process $P_i$ by varying a stagger value, which we denote $z_i$. The stagger value specifies by how many ticks we will advance the invocation of $P_i$. When considering stagger values, each process $P_i$ will run whenever \begin{equation} \label{eq:cdta0:spsi0:02} (t + z_i) \bmod T_i = 0 . \end{equation} At each tick, each process $P_i$ is either scheduled to run or not scheduled to run. We define an infinite row vector, called the \emph{uncosted invocation sequence} (or simply the \emph{invocation sequence}) and denoted $\rho_i(z_i)$, which contains a `1' in each column corresponding to a tick when the process $P_i$ run or `0' if it does not run. For example, if $T_1 = 3$, \begin{eqnarray} \nonumber \rho_1 = \rho_1(0) & = & [ \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; \ldots \; ] \\ \label{eq:cdta0:spsi0:03} \rho_1(1) & = & [ \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; \ldots \; ] \\ \nonumber \rho_1(2) & = & [ \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; \ldots \; ] \\ \nonumber \rho_1(3) & = & [ \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; \ldots \; ] \end{eqnarray} \noindent{}We define but avoid using stagger values $z_i \geq T_i$, but as (\ref{eq:cdta0:spsi0:03}) shows, when it is necessary we define these so that $\rho_i(z_i) = \rho_i(z_i \bmod T_i)$. Also as shown in (\ref{eq:cdta0:spsi0:03}), we use that notation that $\rho_i = \rho_i(0)$. We define the \emph{costed invocation sequence}, denoted $\overline{\rho_i}(z_i)$, as the infinite row vector similar to (\ref{eq:cdta0:spsi0:03}) but where the cost $\tau_i$ is used in place of `1' when a process $P_i$ runs. For example, if $T_1=3$ and $\tau_i = 5$, \begin{eqnarray} \nonumber \overline{\rho_1} = \overline{\rho_1}(0) & = & [ \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; \ldots \; ] \\ \label{eq:cdta0:spsi0:04} \overline{\rho_1}(1) & = & [ \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; \ldots \; ] \\ \nonumber \overline{\rho_1}(2) & = & [ \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; \ldots \; ] \\ \nonumber \overline{\rho_1}(3) & = & [ \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; \ldots \; ] \end{eqnarray} We define the \emph{cost calculation matrix} as the matrix formed by vertically concatenating, in order, the first $LCM(T_1, \ldots , T_N)$ columns of either the uncosted invocation sequence $\rho_i(z_i)$ or the costed invocation sequence $\overline{\rho_i}(z_i)$ of every process in the system; and then appending to this as a row vector the sums of each column. We choose only the first $LCM(T_1, \ldots , T_N)$ columns because the contents of these columns repeat in subsequent columns forever. We denote the cost calculation matrix as $\xi(\mathbf{z})$ (in the case of the uncosted invocation sequences) or as $\overline{\xi}(\mathbf{z})$ (in the case of the costed invocation sequences); where $\mathbf{z}$ is the column vector consisting of all of the staggers $z_i$. Finally, we define the \emph{cost}, denoted $\xi$, as the maximum element from the last row of the cost calculation matrix (it is $\xi$ that we seek to minimize by choosing $\mathbf{z}$). These definitions are illustrated in the following example. \begin{vworkexamplestatement} \label{ex:cdta0:spsi0:01} For the system of 3 processes ($P_1$, $P_2$, and $P_3$) with $T_1=6$, $T_2=4$, $T_3=3$, $\tau_1=2$, $\tau_2=7$, $\tau_3=5$, $z_1 = 2$, $z_2 = 1$, and $z_3 = 0$, form the uncosted and costed invocation sequences, the cost calculation matrices, and the costs. \end{vworkexamplestatement} \begin{vworkexampleparsection}{Solution} We first handle the uncosted case in full, followed by the costed case in full. \textbf{(Uncosted Case):} With $T_1=6$ and $z_1=2$, the first invocation of $P_1$ will occur when $(t + 2) \bmod 6 = 0$ (see Eq. \ref{eq:cdta0:spsi0:02}), at $t=4$, and then repeat with periodicity 6. Thus \begin{equation} \label{eq:ex:cdta0:spsi0:01:01} \rho_1(2) = [ \; 0 \; 0 \; 0 \; 1 \; 0 \; 0 \; 0 \; 0 \; 0 \; 1 \; 0 \; 0 \; 0 \; 0 \; 0 \; 1 \; 0 \; \ldots \; ] . \end{equation} \noindent{}Applying the same definition for $P_2$ and $P_3$ yields \begin{equation} \label{eq:ex:cdta0:spsi0:01:02} \rho_2(1) = [ \; 0 \; 0 \; 1 \; 0 \; 0 \; 0 \; 1 \; 0 \; 0 \; 0 \; 1 \; 0 \; 0 \; 0 \; 1 \; 0 \; 0 \; \ldots \; ] \end{equation} \noindent{}and \begin{equation} \label{eq:ex:cdta0:spsi0:01:03} \rho_3(0) = \rho_3 = [ \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; 1 \; 0 \; 0 \; \ldots \; ] . \end{equation} We note that the column vector $\mathbf{z}$ is \begin{equation} \label{eq:ex:cdta0:spsi0:01:04} \mathbf{z} = \left[\begin{array}{c}z_1\\z_2\\z_3\end{array}\right] = \left[\begin{array}{c}2\\1\\0\end{array}\right] . \end{equation} $LCM(T_1, T_2, T_3) = LCM(6, 4, 3) = 12$, and so the cost calculation matrix can be constructed with only 12 columns, since the columns repeat with periodicity 12: \begin{equation} \label{eq:ex:cdta0:spsi0:01:05} \xi(\mathbf{z}) = \xi\left(\left[\begin{array}{c}2\\1\\0\end{array}\right]\right) = \left[ \begin{array}{rrrrrrrrrrrr} 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 1 \\ 0 & 0 & 2 & 1 & 0 & 1 & 1 & 0 & 1 & 1 & 1 & 1 \end{array} \right] . \end{equation} Note in (\ref{eq:ex:cdta0:spsi0:01:05}) that the last row is the column-wise sum of the rows above it. Note also that the last row gives, on a per tick basis, the number of processes that run. The cost $\xi$ is the maximum of the last row of (\ref{eq:ex:cdta0:spsi0:01:05}), and by inspection $\xi = 2$. \textbf{(Costed Case):} The costed invocation sequences are simply (\ref{eq:ex:cdta0:spsi0:01:01}), (\ref{eq:ex:cdta0:spsi0:01:02}), and (\ref{eq:ex:cdta0:spsi0:01:02}) with 1's replaced by the cost appropriate to the process being considered; $\tau_1$, $\tau_2$, or $\tau_3$: \begin{eqnarray} \nonumber \overline{\rho_1}(2) & = & [ \; 0 \; 0 \; 0 \; 2 \; 0 \; 0 \; 0 \; 0 \; 0 \; 2 \; 0 \; 0 \; 0 \; 0 \; 0 \; 2 \; 0 \; \ldots \; ] \\ \label{eq:ex:cdta0:spsi0:01:06} \overline{\rho_2}(1) & = & [ \; 0 \; 0 \; 7 \; 0 \; 0 \; 0 \; 7 \; 0 \; 0 \; 0 \; 7 \; 0 \; 0 \; 0 \; 7 \; 0 \; 0 \; \ldots \; ] \\ \nonumber \overline{\rho_3}(0) = \overline{\rho_3} & = & [ \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; 5 \; 0 \; 0 \; \ldots \; ] \end{eqnarray} The cost calculation matrix in the costed case is formed by vertically concatenating the first 12 columns of the rows of (\ref{eq:ex:cdta0:spsi0:01:06}), with the final row containing columnwise sums: \begin{equation} \label{eq:ex:cdta0:spsi0:01:07} \overline{\xi}(\mathbf{z}) = \overline{\xi}\left(\left[\begin{array}{c}2\\1\\0\end{array}\right]\right) = \left[ \begin{array}{rrrrrrrrrrrr} 0 & 0 & 0 & 2 & 0 & 0 & 0 & 0 & 0 & 2 & 0 & 0 \\ 0 & 0 & 7 & 0 & 0 & 0 & 7 & 0 & 0 & 0 & 7 & 0 \\ 0 & 0 & 5 & 0 & 0 & 5 & 0 & 0 & 5 & 0 & 0 & 5 \\ 0 & 0 & 12 & 2 & 0 & 5 & 7 & 0 & 5 & 2 & 7 & 5 \end{array} \right] . \end{equation} The cost $\overline{\xi}$ is the maximum of the last row of (\ref{eq:ex:cdta0:spsi0:01:07}), and by inspection $\overline{\xi} = 12$. \end{vworkexampleparsection} \vworkexamplefooter{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Sine And Cosine} %Section tag: sco0 \label{cdta0:ssco0} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Rotational Transformations In 2 Dimensions} %Section tag: RTR2 \label{cdta0:srtr2} \index{rotation!2-D}It occurs often in microcontroller work that one needs to rotate coordinates in 2 dimensions (Figure \ref{fig:cdta0:srtr2:01}). In this section, the most economical algorithms known for 2-dimensional rotation are discussed. We assume that the point $\mathbf{p}$ to be rotated is specified in rectangular coordinates $\mathbf{p} = (p_x, p_y)$ rather than polar coordinates $\mathbf{p} = (r, \theta)$; since if $\mathbf{p}$ is specified in polar coordinates rotation involves only addition to $\theta$ modulo $2\pi$. We denote the point to be rotated $\mathbf{p} = (p_x, p_y) = \left[\begin{array}{c}p_x\\p_y\end{array}\right]$ and the result of the rotation $\mathbf{q} = (q_x, q_y) = \left[\begin{array}{c}q_x\\q_y\end{array}\right]$. We denote the length of the vector represented by $\mathbf{p}$ or $\mathbf{q}$ by $r$, and note that $r = |\mathbf{p}| = \sqrt{p_x^2 + p_y^2} = |\mathbf{q}| = \sqrt{q_x^2 + q_y^2}$. Because low-cost microcontrollers are used, we assume that $p_x, p_y, q_x, q_y \in \vworkintset$. We denote the desired amount of counter-clockwise rotation by $\delta$ (in radians). \begin{figure} \begin{huge} \begin{center} Reserved \end{center} \end{huge} \caption{Rotation In 2 Dimensions} \label{fig:cdta0:srtr2:01} \end{figure} A particularly na\"{\i}ve algorithm to use in microcontroller work is to convert $\mathbf{p} = (p_x, p_y)$ to polar coordinates $\mathbf{p} = (r, \theta)$, rotate to obtain $\mathbf{q} = (r, (\theta + \delta) \bmod 2\pi)$, and then convert back to rectangular coordinates $\mathbf{q} = (q_x, q_y)$. This algorithm is na\"{\i}ve because trigonometric and inverse trigonometric functions are required, which are not economical to implement on microcontrollers. We seek if possible algorithms which operate exclusively in rectangular coordinates and which require little or no evaluation of trigonometric and inverse trigonometric functions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Matrix Rotation In 2 Dimensions} %Section tag: MRT0 \label{cdta0:srtr2:smrt2} Assume we wish to rotate the vector \begin{equation} \label{eq:cdta0:srtr2:smrt2:01} \mathbf{p} = (p_x, p_y) = \left[\begin{array}{c}p_x\\p_y\end{array}\right] = (r \cos \theta, r \sin \theta) = \left[\begin{array}{c}r \cos \theta\\r \sin \theta\end{array}\right] \end{equation} \noindent{}by an angle of $\delta$ to give the vector \begin{eqnarray} \label{eq:cdta0:srtr2:smrt2:02} \mathbf{q} & = & (q_x, q_y) = \left[\begin{array}{c}q_x\\q_y\end{array}\right] \\ \nonumber & = & (r \cos (\theta + \delta), r \sin (\theta + \delta)) = \left[\begin{array}{c}r \cos (\theta + \delta)\\r \sin (\theta+\delta)\end{array}\right]. \end{eqnarray} \noindent{}Recall from standard trigonometry identities that for sines and cosines of sums of angles that \begin{eqnarray} \label{eq:cdta0:srtr2:smrt2:03} \left[\begin{array}{c}r \cos (\theta + \delta)\\r \sin (\theta+\delta)\end{array}\right] & = & \left[\begin{array}{c}r \cos \theta \cos \delta - r \sin \theta \sin \delta \\ r \sin \theta \cos \delta + r \cos \theta \sin \delta \end{array}\right] \\ \label{eq:cdta0:srtr2:smrt2:04} & = & \left[\begin{array}{c}p_x \cos \delta - p_y \sin \delta \\ p_x \sin \delta + p_y \cos \delta \end{array}\right] \\ \label{eq:cdta0:srtr2:smrt2:05} & = & \left[\begin{array}{c}q_x\\q_y\end{array}\right] = \left[\begin{array}{cc}\cos \delta & - \sin \delta \\ \sin \delta & \;\;\;\cos \delta \end{array}\right] \left[\begin{array}{c}p_x\\p_y\end{array}\right] . \end{eqnarray} \noindent{}Note that (\ref{eq:cdta0:srtr2:smrt2:05}) reduces the rotation problem to four multiplications and two additions (the matrix multiplication), provided that some approximation of the sine and cosine functions is available (see Section \ref{cdta0:ssco0}). To apply (\ref{eq:cdta0:srtr2:smrt2:05}), the embedded software may or may not need to approximate the sine and cosine functions. For some applications, if the angle of rotation is fixed, $\sin \delta$ and $\cos \delta$ may be calculated at compile time and tabulated in ROM rather than $\delta$ (so that the embedded software does not need to approximate these functions). For other applications, sine and cosine must be approximated (see Section \ref{cdta0:ssco0}). The 2 $\times$ 2 matrix in (\ref{eq:cdta0:srtr2:smrt2:05}) is called the \index{rotation matrix}\emph{rotation matrix}. There are other functionally equivalent ways to derive this result, including complex arithmetic (i.e. phasor analysis) and graphical geometric arguments. As pointed out in Section \ref{cdta0:ssco0}, the best way to approximate sine and cosine in low cost microcontrollers is usually by tabulation of the values of $\sin \delta$ for $\delta \in [0, \pi/2]$. Using the techniques presented in Section \ref{cdta0:ssco0} for approximation of sine and cosine and using (\ref{eq:cdta0:srtr2:smrt2:05}), rotation can usually be carried out using around 20 machine instructions. If a vector is rotated repeatedly using (\ref{eq:cdta0:srtr2:smrt2:05}), cumulative truncation and rounding errors may eventually yield a vector $\mathbf{q}$ with a significantly different magnitude $|\mathbf{q}| = \sqrt{q_x^2 + q_y^2}$ than the starting vector. It should be possible to develop an algorithm similar in spirit to the Bresenham circle algorithm (see Section \ref{cdta0:srtr2:sbrt2}) to adjust the magnitude of a vector to correct for cumulative errors while leaving its direction as nearly unchanged as possible (see Exercise \ref{exe:cdta0:sexe0:01}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Bresenham Rotation In 2 Dimensions} %Section tag: BRT0 \label{cdta0:srtr2:sbrt2} Depending on the application \ldots{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Rotational Transformations In 3 Dimensions} %Section tag: RTR3 \label{cdta0:srtr3} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Acknowledgements} %Section tag: ACK0 \label{cdta0:sack0} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Exercises} %Section tag: sexe0 \label{cdta0:sexe0} \begin{vworkexercisestatement} \label{exe:cdta0:sexe0:01} Develop an algorithm similar in spirit to the Bresenham circle algorithm to adjust a vector $\mathbf{q} = (q_x, q_y)$ with cumulative magnitude errors due to repeated rotations to a vector $\mathbf{z} = (z_x, z_y)$ which points as nearly as possible in the same direction as $\mathbf{q}$ but with a desired magnitude $r$. \end{vworkexercisestatement} \vworkexercisefooter{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \vfill \noindent\begin{figure}[!b] \noindent\rule[-0.25in]{\textwidth}{1pt} \begin{tiny} \begin{verbatim} $RCSfile: c_dta0.tex,v $ $Source: /home/dashley/cvsrep/e3ft_gpl01/e3ft_gpl01/dtaipubs/esrgubka/c_dta0/c_dta0.tex,v $ $Revision: 1.5 $ $Author: dtashley $ $Date: 2003/03/03 23:50:43 $ \end{verbatim} \end{tiny} \noindent\rule[0.25in]{\textwidth}{1pt} \end{figure} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % $Log: c_dta0.tex,v $ % Revision 1.5 2003/03/03 23:50:43 dtashley % Substantial edits. Safety checkin. % % Revision 1.4 2003/02/27 05:00:06 dtashley % Substantial work towards rotation algorithm section. % % Revision 1.3 2003/01/15 06:23:13 dtashley % Safety checkin, substantial edits. % % Revision 1.2 2003/01/14 05:39:59 dtashley % Evening safety checkin after substantial edits. % % Revision 1.1 2001/08/25 22:51:25 dtashley % Complex re-organization of book. % %End of file C_PCO0.TEX