A method to convert floating to fixedpoint EKFSLAM for embedded robotics
 Leandro de Souza Rosa^{2, 1}Email author and
 Vanderlei Bonato^{1}
https://doi.org/10.1007/s1317301200924
© The Brazilian Computer Society 2012
Received: 20 February 2012
Accepted: 15 October 2012
Published: 8 November 2012
Abstract
The Extended Kalman Filter (EKF) is one of the most efficient algorithms to address the problem of Simultaneous Localization And Mapping (SLAM) in the area of autonomous mobile robots. The EKF simultaneously estimates a model of the environment (map) and the position of a robot based on sensor information. The EKF for SLAM is usually implemented using floatingpoint data representation demanding high computational processing power, mainly when the processing is performed online during the environment exploration. In this paper, we propose a method to automatically estimate the bitrange of the EKF variables to mitigate its implementation using only fixedpoint representation. In this method is presented a model to monitor the algorithm stability, a procedure to compute the bit range of each variable and a first effort to analyze the maximum acceptable system error. The proposed system can be applied to reduce the overall system cost and power consumption, specially in SLAM applications for embedded mobile robots.
Keywords
1 Introduction
The Extended Kalman Filter (EKF) [1] is one of the most important algorithms in the area of mobile robotics for the localization and mapping tasks due to its ability to deal with noise and its high degree of accuracy [2]. Derived from Bayesian filters [3], EKF has high computational complexity and performs operations over a large volume of data. Applying such a solution in the development of embedded mobile robots is highly desired, since it allows one to build intelligent machines capable of acting autonomously in complex environments.
Implementing this algorithm in a customized device is usually desired when a typical solution of a general purpose processor is unsatisfactory, such as when the robotic system has limited cost, performance and power requirements. Developing an optimized processing system, such as the one presented in Bonato et al. [4], where an EKF floatingpoint based system on an FPGA (FieldProgrammable Gate Array) was implemented, is a feasible way to achieve the requirements via specific customizations of software and hardware. Customized system operating over fixedpoint format is another way to obtain further optimizations for embedded robotic applications.
There are different ways to convert algorithms from floatingpoint to fixedpoint format. Most solutions are completely automatic and orientated to DSP applications [5, 6]. The main task in converting an algorithm is to estimate the bitrange of each single variable in such way to avoid an error bigger than the one allowed by the algorithm without compromising the overall system accuracy, which can be caused by underflows and overflows of variables.
Recent work has used fixedpoint representation to implement the EKF algorithm to solve the SLAM problem. In Moyers et al. [7], we have a fixedpoint implementation, but without bit length optimization, and in, Mingas et al. [8], there exists another fixedpoint implementation, with bit lengths of all variables defined by physical constraints of a robot. In this paper is the first work that presents an approach to estimate a particular bit length for each according to a maximum error defined by the user. The main contributions of this paper are:

a method to monitor the EKF error during the conversion process;

an optimized way to reduce the time needed for the conversion process;

the bit range of each EKF variable for a given maximum error.
The paper is organized as follows. Section 2 briefly introduces the EKF algorithm for SLAM along with a table describing each of its variables. Section 3 presents the floating to fixedpoint conversion algorithm steps, which was adapted from Roy and Banerjee [9]. The error analysis method is demonstrated in Sect. 4 followed by Sect. 5, where the conversion results are presented. Finally, Sect. 6 concludes the paper.
2 Extended Kalman Filter
This section briefly describes the EKF algorithm and a complete description, with the derivation of each equation, can be found in [2]. The source code used as base in our work can be founded in Newman [10].
2.1 EKF description
EKF is composed of two phases: prediction and update. In the SLAM context, the prediction phase estimates the robot position \(\mu _v^{(t)}\), at time \(t\), based on a prior believed position \(\mu _v^{(t1)}\) and on a movement control \(u^{(t)}\), while the update phase integrates robot sensor observations \(z^{(t)}\) in order to update a map of the robot environment and to, again, estimate the robot position. These two steps are repeated for each EKF iteration, where the data estimated at one iteration are used as input to the next one.
Table 1 describes the variables used in the prediction and update EKF equations along with their dimensions. Equations (2) and (3) are used to estimate the new robot position given the belief vector \(\mu _v^{(t1)}\) and the covariance matrix that correspond to the robot position \(\Sigma _{vv}^{(t1)}\) and the current motion control \(u^{(t)}\). \(F^{(t)}\) and \(G^{(t)}\) are Jacobian matrices containing derivatives of the prediction function \(\alpha \) with respect to the motion command variables at time \(t\). Equation (4) estimates the covariance between the robot and feature position \(\Sigma _{vf}\) given the corresponding covariance from time \((t1)\) and the matrix \(F^{(t)}\).
After computing the prediction equations, the update step starts by predicting the sensor measurement through the measurement function equation (9) using the estimated robot position \(\mu _{v}^{(t)}\) and the detected feature \(\mu _{fi}^{(t1)}\). Then, Eqs. (10) and (11) calculate the innovation related to the measurement \(\nu ^{(t)}\) and covariance \(S^{(t)}\), respectively. \(\nu ^{(t)}\) is the difference between the real and the estimated sensor measurement and \(S^{(t)}\) is the new information added to the system covariance given the current matrix \(H^{(t)}\) and the covariance from the previous prediction phase. \(H^{(t)}\) is a matrix that compounds two Jacobian matrices \(H_v^{(t)}\) and \(H_{fi}^{(t)}\) from (8) which are derivatives of the prediction function \(\gamma \) with respect to the estimated robot position and the detected feature at time \(t\). Then, Eq. (12) computes the filter weight. Finally, Eqs. (5) and (6) update all data that corresponds to the estimated map.
The description and dimension of the EKF symbols, where \(s\) and \(r\) represent the feature and robot state size, \(v\) and \(f\) the robot and feature position, \(i\) the feature number and \(n\) the total number of features
Sym.  Dimension  Description 

\(\mu \)  \((r+sn) \times 1\)  Both robot and feature positions 
\(\mu _v\)  \(r \times 1\)  Elements of \(\mu \) related to robot position 
\(\mu _f\)  \(sn \times 1\)  Elements of \(\mu \) related to feature position 
\(\Sigma _{vv}\)  \(r \times r\)  Robot position covariance 
\(\Sigma _{vf}\)  \(r \times (sn)\)  Cross robotfeature covariance 
\(\Sigma _{ff}\)  \((sn) \times (sn)\)  Cross featurefeature covariance 
\(\Sigma \)  \((r+sn) \times \)  Cross robotfeature 
\((r+sn)\)  and featurefeature covariance  
\(\alpha \)  –  Prediction function 
\(\gamma \)  –  Measurement function 
\(u\)  \(r \times 1\)  Robot motion command 
\(F\)  \(r \times r\)  Robot motion Jacobian 
\(G\)  \(r \times r\)  Robot motion noise Jacobian 
\(Q\)  \(r \times r\)  Permanent motion noise 
\(H_v\)  \(s \times r\)  Measurement Jacobian with respect to \(v\) 
\(H_{fi}\)  \(s \times s\)  Measurement Jacobian with respect to \(f_i\) 
\(H\)  \(s \times (r+sn)\)  Compounded measurement Jacobian 
\(R\)  \(s \times s\)  Permanent measurement noise 
\(W\)  \((r+sn) \times s\)  Filter gain 
\(\nu \)  \(s \times 1\)  Mean innovation 
\(z\)  \(s \times 1\)  Sensor measurement 
\(z_\mathrm{pred}\)  \(s \times 1\)  Sensor measurement prediction 
\(S\)  \(s \times s\)  Covariance innovation 
\(Z_1\)  \(s \times (s(i1))\)  Zero matrix 
\(Z_2\)  \(s \times (s(ni))\)  Zero matrix 
3 Conversion algorithm
In this section, we present the conversion algorithm adapted from Roy and Banerjee [9] to estimate the bitrange of each fixedpoint EKF variable. The algorithm is divided in eight steps. The first two conversion steps, Levelization and Scalarization, are used to modify the algorithm source code to make the process more systematic so as to obtain better results. The third step, Computation of Ranges of Variables, computes the maximum values of each algorithm variable. Then, the fourth step, Evaluate Integer Variables, figures out the variables of the source code that are integers, followed by the fifth and sixth steps, where the source code is converted to fixedpoint representation and the integer range of the fixed point representation of each variable is evaluated, respectively. Finally, the last two steps, Coarse Optimization and Fine Optimization, optimize the final bitrange of each variable.
Comparing this with the conversion algorithm given in Roy and Banerjee [9], the Computation of Ranges of Variables and Fine Optimization were modified, and, the step Evaluate Integer Variables, was added, keeping the other steps as they were.
As input to this conversion procedure, we used a floatingpoint code of the EKF algorithm implemented in Matlab, adapted from Newman [10]. The use of Matlab code is appropriated, since it provides a set of facilities needed by the conversion algorithm. The following subsection starts presenting an introduction to the terms adopted by the conversion procedure. Then, the next subsections describe each conversion step presented along with examples.
3.1 Introduction and nomenclature
The conversion algorithm basically uses the objects ‘quantizer()’ and ‘quantize()’ from the Filter Design Analysis (FDA) toolbox available in the MATLAB [11]. Here, we will use m for the integer and p for the fractional length of any variable. The ‘quantizer()’ function is a constructor to ‘quantize’ objects which allocates the bitwidths and the information about the representation, as if the representation is signed or unsigned, the kind of rounding and the overflow treatment. Furthermore, the ‘quantize()’ applies the ‘quantize’ object in a number, and gives as a return the value of the number represented by an integer data type defined by the ‘quantize’.
For all cases, n is the number of variables that the algorithm to be converted has after the Scalarization step. As each variable has a different number of bits lengths, we represent m, p and q as vectors, of n positions, representing the integerwidth, the fractional width and ‘quantizers’, respectively, for each variable.
3.2 Levelization
3.3 Scalarization
This step converts the vectorized MATLAB statements for scalar ones using FOR loops. The code fragment 3.2 exemplify the scalarization step.
3.4 Computation of ranges of variables
This is the core step for calculating the m values (integer width). First, it is necessary to take the maximum and minimum values of the algorithm’s inputs and then propagate them to the forward direction calculating the maximum and minimum values for each variable. To exemplify this step we are going to use a generic algorithm; the code fragment 3.3 shows an example and Table 2 demonstrates the result of propagation for this code.
As stated in Table 2, there is a problem regarding the division by zero. When it happens, it is necessary to consider a tiny number, say a unit, for the variables with the zero division problem, making the roll back calculation of maximum e minimum values. To finish, we must ensure that the entries are within the limits obtained.
Maximum and Minimum values propagated for the code fragment 3.3
Variable  \(a\)  \(b\)  \(x\)  \(y\)  \(z\)  Output 

Maximum  100  5  500  Error/Inf  Error/Inf  Error/Inf 
Minimum  0  0  0  0  0  1 
Another problem can occur when the algorithm to be converted stays running in FOR loops with feedbacks (some output values are used as entry values in the next loop); in that case, the maximum or minimum values of some variables may grow to infinity. This is the case for our EKF algorithm, leading to a situation where the maximum and minimum values need to be estimated instead of being calculated. To perform such an estimate, we can simply define a training set and evaluate these values while executing the algorithm over this training set. The code fragment 3.4 demonstrates how to calculate the maximum value for a matrix variable. Note that using the absolute value of each variable we don’t have to care about the minimum values of the variables.
The code fragment 3.5 exemplifies the usage of ‘max()’ function from code fragment 3.4, where maximums is a vector that stores the maximum values for each variable.
The problem of this procedure is that we cannot guarantee any overflows during the executions for the cases that do not belong to the training set. For this situation, we need to use a larger training set.
3.5 Evaluate integer variables
The reasoning of this step is to figure out which variables of the algorithm to be converted represent integers values, which usually appear as counters or indices variables. The step described in Sect. 3.8 gives a unique value for all p, including the integer variables, and the step described in 3.9 have to reduce the p values of the integer variables to zero, what may takes a long time. Since the integer variables should be converted too, we can save time in step 3.9 if we know which variable represents integer numbers by simply setting zero to the p values of integer variables.
The idea is to define a \(n\times 1\) boolean vector, say D, where each index corresponds to a variable of the algorithm to be converted after the step 3.3. In this vector, 0 means that the correspondent variable is not an integer, and 1 means that the variable is an integer.
To evaluate which variables are integer we should know exactly which operations (statements, functions and methods) return integer values given their entries.
We define the class “absolute integer return” (AIR) as the class of all operations that returns integers given any kind of entries, and we define the class “linear” as the class of all operations that, given integer values for all entries, returns integer values, finally, we define the class “float return” (FR) as the class of operations that is impossible to guarantee if the return is integer or noninteger values given any kind of entry.
Classification of some comum operations in MATLAB since their return values
AIR  Linear  FR 

Length()  +  / 
Size()  –  rand() 
Numel()  \(*\)  sqrt() 
Ceil()  \(\wedge x (x\ge 0)\)  \(\wedge x (x<0)\) 
Floor()  det()  norm() 
Zeros()  inv()  
Ones()  sin()  
Eye()  cos()  
tan() 
3.6 Generation of fixedpoint MATLAB code
At this point, we see that, in each statement, we have associated an error due to the conversion from floatingpoint to fixedpoint. The EKF equations 2 to 6 show that these errors are incorporated by the \(\Sigma \) matrix and propagated to all other variables. Although these errors are incorporated with the system noise, if we fix the simulated odometry and observation noises, the conversion will generate an error measured by Eq. 17.
When generating the fixedpoint MATLAB code for matrix multiplications we see that scalarizations results in a nonlevelizated statement (as showed in code fragment 3.2 line 7). At first sight, we would have to reapply the levelization step in this statement before the conversion to fixedpoint code, however, with the following Observations 1 and 2 we can see that this “relevelization” is irrelevant and can be skipped. In this way, the converted code for matrix multiplications is exemplified by the code fragment 3.7.
Observation 1
0 = quantize(q, 0) ever!
Observation 2
If we have two variables a and b, and a ‘quantizer’ q, and apply the ‘quantize()’ method over one variable, say a, it will get your value modified, call it as qa. In this way, to add qa with b is different than to add b with a, and as consequence, apply the ‘quantize()’ method over a+b and qa+b will lead us to different results.
3.7 Fixed integral range
3.8 Coarse optimization
3.9 Fine optimization
Given the p by the step in Sect. 3.8, this step estimates the optimized value for each p by analyzing and reducing the p value for each variable. The Algorithm 3.3 resumes the algorithm presented in Roy and Banerjee [9] and adds one more step in it. The first step in Algorithm 3.3 uses the vector D to set zero to the p values corresponding to integer variables, the following steps correspond to the algorithm given by Roy and Banerjee [9] resumed. Setting zero to some p values might impact significantly the Fine Optimization step, as can be seen in Sect. 5.
4 Analysis of the covariance matrix
The conversion algorithm tries to define values for p such that the error, using a training set, remains lower than the error \(E_\mathrm{max}\) given in step 3.2. If the chosen error is small, the p values will be bigger than necessary, on the other hand, if the chosen error is big, the system might diverge.
To define a better \(E_\mathrm{max}\) value, we can analyze the covariance matrices since they incorporate the conversion errors. To compare the covariance matrices is easier than to define a metric that aggregate the information about the covariance ellipses in one curve, and then, compare two curves instead of a couple of matrices entries. Our idea is to observe the lengths of the semiaxis of the ellipses [12] by simply averaging the size of the semiaxis of each ellipse.
In this way, if any ellipse gets a large covariance component in one direction and a small component in another direction, our measure will have a considerable increase. This sensibility could not be reached if we would have considered other metrics, like area, this would not be interesting since the uncertainty about the feature position is actually high.
After the conversion is done, we are able to decrease p values and make another evaluation like the one shown in Fig. 5 and compare them to decide if the \(E_\mathrm{max}\) chosen fits well. In our tests we decided to decrease one bit of each variable between comparisons to increase the error. Figure 6 shows the evaluations obtained. Observing the graphics in Fig. 6 a new error is chosen and the conversion algorithm is applied again to find new suitable values for m and p.
5 Preliminary results
In this section we present the main results of this work. The first one is the algorithm, which was adapted from Roy and Banerjee [9] to convert the EKFSLAM; the second one is the time that the conversion takes to finish; and the third one is the bit range for each of the EKFSLAM variables. We used a simple configuration with a small training set in order to make the conversion faster. Real applications may need a bigger training set in order to have a better tuning for the bit range of the EKF variables.
5.1 Processing time
The error is calculated taking the maximum error between the execution of the floatingpoint code and the fixedpoint code over the entire training set. Given \(x\) elements in the training set, for each error calculation the fixedcode and the floatingcode are executed \(x\) times. If we say that the fixedcode takes \(t_\mathrm{fixed}\) and the floating \(t_\mathrm{float}\) seconds, we have, approximately \(t_\mathrm{error} = x(t_\mathrm{fixed}+t_\mathrm{float})\) seconds for calculating the error.
The maximums values are calculated once running once the floatingcode over the training set, so we can say that \(t_\mathrm{maximums} \approx xt_\mathrm{float}\). We are going do disregard the time for calculating the p values because it is faster than the error calculation. Since the coarse optimization performs a binary search between \([0,32]\) we have \(t_\mathrm{coarse} = 3t_\mathrm{error}\log _232 \approx 15t_\mathrm{error}\).
The \(t_\mathrm{maximuns}\) have no meaning in the original algorithm presented by Roy and Banerjee [9], the \(t_\mathrm{error}\) can be very different in the original and in the modified conversions, which depends on the training set size. However, \(t_\mathrm{coarse} \approx 15t_\mathrm{error}\) in both implementations.
Supposing that the coarse optimization gave a \(p_0\) value for p, that we have \(n_i\) integer variables found in step (Sect. 3.5), \((0\le n_i\le n)\), and that we have the final values of p. Then, the number of bits reduced in the fine optimization step is \(np_0  \sum _{i=1}^np[i]\). For each bit reduced, the algorithm calculates the error n times, so, in the original algorithm we have \(t_\mathrm{fine}^o=n(np_0 \sum _{i=1}^np[i])t_\mathrm{error}^o\). In the modified version we have that \(n_i\) variables have their p values set to zero instead of leaving it decreased to zero by the conversion algorithm. This saves \(p_0.n_i\) to be reduced, therefore, in the modified algorithm we have \(t_\mathrm{fine}^m=n(p_0(nn_i)\sum _{i=1}^np[i])t_\mathrm{error}^m\) (here, “\({^o}\)” and “\({^m}\)” indicate the times referents to the original and modified algorithm, respectively).
We call by modified algorithm the algorithm with the Evaluate Integer Variables step (Sect. 3.5). It is worth noticing that the time saved by adding this step varies from algorithm to algorithm to be converted, the more integer variables, more time will be saved. Furthermore, since we had modified the original algorithm, it is impossible to compare the estimative time with it.
In our EKFSLAM conversion we adopted \(n=107\), \(n_i=17\), \(p_0 = 25\) and \(\sum _{i=1}^np[i] = 481\), which gave us \(t_\mathrm{fine}^o = 234758t_\mathrm{error}^o\) and \(t_\mathrm{fine}^m = 189283t_\mathrm{error}^m\) meaning that the usage of step 3.5 saved \(19.37~\%\) of the execution time of our fine optimization step.
5.2 Bitrange obtained
As mentioned in Sect. 4, the chosen \(E_\mathrm{max}\) might not be the best value at first try. However, in order to evaluate our conversion algorithm \(E_\mathrm{max} = 0.01~\%\) was chosen. Based on this error, the bit range of the variables was reduced interaction after interaction generating, as a result the graphics shown in Fig. 6. These graphics show the average size of the ellipses semiaxis of the float implementation, of the fixed implementation and of the fixed implementation when we reduced \(j\) bits from each value of p, which has different values in each position.
In Fig. 6, we can see that the shape of the curve changes when \(j=5\). When \(j=10\), we already can see several differences, and when \(j=12\) the fixed implementation diverges. To choose a better \(E_\mathrm{max}\), say \(E_\mathrm{max}^\mathrm{new}\), we can compare the graphics from Fig. 6. Since \(j=2\) gave us a small difference when comparing with the float graphic, and its error was \(1.17~\%\), we choose as new error \(E_\mathrm{max}^\mathrm{new} = 1.00~\%\).
The dimension, \(m_0\), \(p_0\) given by the conversion with \(E_\mathrm{max} = 0.01~\%\) and \(m_f, p_f\) for \(E_\mathrm{max}^\mathrm{new} = 1.0~\%\) of the EKF symbols obtained, where \(s\) and \(r\) represent the feature and robot state size, \(v\) and \(f\) the robot and feature position, \(i\) the feature number and \(n\) the total number of features
Sym.  \(m_0\)  \(p_0\)  \(m_f\)  \(p_f\) 

\(\mu \)  12  22  12  22 
\(\mu _v\)  2  25  2  25 
\(\mu _f\)  12  25  12  25 
\(\Sigma _{vv}\)  16  25  16  25 
\(\Sigma _{vf}\)  16  25  16  25 
\(\Sigma _{ff}\)  18  25  18  25 
\(\Sigma \)  13  24  13  24 
\(\alpha \)  –  –  –  – 
\(\gamma \)  –  –  –  – 
\(u\)  2  25  2  25 
\(F\)  5  25  5  25 
\(G\)  5  25  5  25 
\(Q\)  5  25  5  19 
\(H_v\)  6  23  6  19 
\(H_{fi}\)  6  25  6  19 
\(H\)  6  25  6  19 
\(R\)  15  25  15  19 
\(W\)  10  24  10  19 
\(\nu \)  11  25  11  19 
\(z\)  12  25  12  19 
\(z_\mathrm{pred}\)  12  25  12  19 
\(S\)  15  25  15  19 
\(Z_1\)  –  –  –  – 
\(Z_2\)  –  –  –  – 
6 Conclusion
The paper has presented a method to convert the EKF algorithm from floatingpoint to fixedpoint representation. The method demonstrates a way to measure the EKF computation error, which is crucial for guiding the conversion process. As a final result, a table is presented demonstrating the integer and fractional bit range needed for each EKF variable.
The EKF algorithm is widely used in mobile robotics to solve the problem of navigation and localization. The fixedpoint version presented in this paper might have a significant impact on embedded mobile robotic applications, since the hardware complexity needed to operate over fixedpoint data is simpler and faster than any floatingpoint processing unit. As a consequence, the computation systems can be very optimized in relation to energy consumption, performance, and cost.
Finally, the case study presented in this paper is an EKF for SLAM problem in a twodimensional planar coordinate system. However, the proposed method can be applied to higher dimensions, since the conversion algorithm and the error measure procedure are independent of the dimensions of the environment representation.
Declarations
Acknowledgments
The authors would like to thank FAPESP (Ref. 2010/055084) for the financial support given to develop this research project.
Authors’ Affiliations
References
 Smith R, Self M, Cheeseman P (1990) Estimating uncertain spatial relationships in robotics. Auton Robot Vehicles 8:167–193View ArticleGoogle Scholar
 Thrun S, Burgard W, Fox D (2005) Probabilistic robotics. MIT Press, CambridgeMATHGoogle Scholar
 Fox D, Hightower J, Liao L, Schultz D, Borriello G (2003) Bayesian filters for location estimation. IEEE Pervasive Comput 2(3):24–33View ArticleGoogle Scholar
 Bonato V, Marques E, Constantinides GA (2009) A floatingpoint extended Kalman filter implementation for autonomous mobile robots. J VLSI Sig Proc 56:41–50Google Scholar
 Xilinx (2006) AccelDSP synthesis tool floatingpoint to fixedpoint conversion of MATLAB algorithms targeting FPGAs. Xilinx Inc.Google Scholar
 Belanović P, Rupp M (2005) Automated floatingpoint to fixedpoint conversion with the fixify environment. In: 16th International workshop on rapid system prototypingGoogle Scholar
 Moyers M, Stevens D, Chouliaras V, Mulvaney D (2009) Implementation of a fixedpoint FastSLAM 2.0 algorithm on a configurable and extensible VLIW processor. In: IEEE international conference on eletronics circuits and systems (ICECS), TunisiaGoogle Scholar
 Mingas G et al (2011) An FPGA implementation of the SMGSLAM algorithm. Microprocess Microsyst. doi: 10.1016/j.micpro.2011.12.002Google Scholar
 Roy S, Banerjee P (2004) An algorithm for converting floatingpoint computations to fixedpoint in MATLAB based FPGA design. In: Annual ACM IEEE design automation conference proceedings of the 41st annual design automation, pp 484–487Google Scholar
 Newman PM (2005) C4B—mobile robotics, version 2.0. Robotics Research Group, The Department of Engineering Science, University of Oxford. http://www.robots.ox.ac.uk/~pnewman/Teaching/C4CourseResources/C4BResources.html. Accessed Aug 2011
 MathWorks (2010) Fixedpoint toolbox TM user’s guide. http://www.mathworks.com/help/pdf_doc/fixedpoint/FPTUG.pdf. Accessed Aug 2011
 Stuart A, Ord JK (1994) Kendall’s advanced theory of statistics, vol I, 6th edn. Hodder Arnold, New YorkGoogle Scholar
 Wolf PR, Ghilani CD (1997) Adjustment computations—statistics and least squares in surveying and GIS, Chap 5, 3rd edn. Wiley, New YorkGoogle Scholar