diff --git a/localization/doc.txt b/localization/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6c2ec8893f289a025937543ede7f0c6b47e7841b
--- /dev/null
+++ b/localization/doc.txt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    localization LOCALIZATION
+ * @brief       localization and optimization algorithms of distance- and magnetic-based 
+ *              localization systems.
+ *
+ * @details     The localization module contains functions to compute a position of a mobile device 
+ *              using distance measurements or DC-pulsed, magnetic signals. This module also includes 
+ *              optimization algorithms such as the Levenberg--Marquardt approach to optimize the 
+ *              calculated position. The localization module also involves a method to recognize and 
+ *              mitigate the multipath errors on the mobile station.
+ *
+ * @author      Zakaria Kasmi
+ *
+ */
diff --git a/localization/position_algos/distance_based/dist_based_fi.c b/localization/position_algos/distance_based/dist_based_fi.c
new file mode 100644
index 0000000000000000000000000000000000000000..73fb25b7ca7fc025f97967e3bc0a7fc64d154201
--- /dev/null
+++ b/localization/position_algos/distance_based/dist_based_fi.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Error function of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <math.h>
+
+#include "matrix.h"
+
+matrix_t dist_based_fi(matrix_t point[3], matrix_t ref_point[3], matrix_t ri)
+{
+
+    matrix_t f_i =
+        sqrt(
+            (point[0] - ref_point[0])
+            * (point[0]
+               - ref_point[0])
+            +
+            (point[1] - ref_point[1])
+            * (point[1]
+               - ref_point[1])
+            +
+            (point[2] - ref_point[2])
+            * (point[2]
+               - ref_point[2])
+            ) - ri;
+
+    return f_i;
+}
+
+void dist_based_f_i(uint8_t ref_points_num,
+                    matrix_t ref_point_mat[ref_points_num][3],
+                    matrix_t point[3],
+                    matrix_t d_vec[], matrix_t f_vec[])
+{
+    uint8_t i;
+
+    for (i = 0; i < ref_points_num; i++) {
+        f_vec[i] =
+            sqrt(
+                (point[0] - ref_point_mat[i][0])
+                * (point[0]
+                   - ref_point_mat[i][0])
+                +
+                (point[1]
+                 - ref_point_mat[i][1])
+                * (point[1]
+                   - ref_point_mat[i][1])
+                +
+                (point[2]
+                 - ref_point_mat[i][2])
+                * (point[2]
+                   - ref_point_mat[i][2])
+                )
+            - d_vec[i];
+    }
+}
diff --git a/localization/position_algos/distance_based/dist_based_jacobian.c b/localization/position_algos/distance_based/dist_based_jacobian.c
new file mode 100644
index 0000000000000000000000000000000000000000..117624ed75317b54d0775526caadf4a07a2bb0d4
--- /dev/null
+++ b/localization/position_algos/distance_based/dist_based_jacobian.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Jacobian function of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <math.h>
+
+#include "matrix.h"
+#include "vector.h"
+#include "dist_based_fi.h"
+
+void dist_based_jacobian_get_JTf(uint8_t ref_points_num,
+                                 matrix_t ref_point_matrix[ref_points_num][3],
+                                 matrix_t point[3],
+                                 matrix_t dist_vec[ref_points_num],
+                                 vector_t JTf[3])
+{
+    uint8_t i;
+    matrix_t f_i = 0.0;
+    matrix_t denom = 0.0;
+
+    vector_clear(3, JTf);
+    for (i = 0; i < ref_points_num; i++) {
+        f_i =
+            dist_based_fi(point,
+                          (matrix_t *)&ref_point_matrix[i],
+                          dist_vec[i]);
+        denom = f_i + dist_vec[i];
+        if (denom != 0) {
+            JTf[0] += (point[0] - ref_point_matrix[i][0]) * f_i
+                      / denom;
+            JTf[1] += (point[1] - ref_point_matrix[i][1]) * f_i
+                      / denom;
+            JTf[2] += (point[2] - ref_point_matrix[i][2]) * f_i
+                      / denom;
+        }
+    }
+}
+
+void dist_based_jacobian_get_JTJ(uint8_t ref_points_num,
+                                 matrix_t ref_point_matrix[ref_points_num][3],
+                                 matrix_t point[3],
+                                 matrix_t dist_vec[ref_points_num],
+                                 matrix_t JTJ[3][3])
+{
+    uint8_t i;
+    matrix_t denom = 0.0;
+    matrix_t f_i = 0.0;
+
+    matrix_clear(3, 3, JTJ);
+    for (i = 0; i < ref_points_num; i++) {
+        f_i =
+            dist_based_fi(point,
+                          (matrix_t *)&ref_point_matrix[i],
+                          dist_vec[i]) + dist_vec[i];
+        denom = f_i * f_i;
+        if (denom != 0) {
+            JTJ[0][0] += (point[0] - ref_point_matrix[i][0]) *
+                         (point[0] - ref_point_matrix[i][0])
+                         / denom;
+            JTJ[1][1] += (point[1] - ref_point_matrix[i][1]) *
+                         (point[1] - ref_point_matrix[i][1])
+                         / denom;
+            JTJ[2][2] += (point[2] - ref_point_matrix[i][2]) *
+                         (point[2] - ref_point_matrix[i][2])
+                         / denom;
+            JTJ[0][1] += (point[0] - ref_point_matrix[i][0]) *
+                         (point[1] - ref_point_matrix[i][1])
+                         / denom;
+            JTJ[0][2] += (point[0] - ref_point_matrix[i][0]) *
+                         (point[2] - ref_point_matrix[i][2])
+                         / denom;
+            JTJ[1][2] += (point[1] - ref_point_matrix[i][1]) *
+                         (point[2] - ref_point_matrix[i][2])
+                         / denom;
+        }
+    }
+
+    JTJ[1][0] = JTJ[0][1];
+    JTJ[2][0] = JTJ[0][2];
+    JTJ[2][1] = JTJ[1][2];
+}
+
+void dist_based_jacobian_get_J(uint8_t ref_points_num, matrix_t point[3],
+                               matrix_t ref_point_matrix[ref_points_num][3],
+                               matrix_t J[ref_points_num][3])
+{
+    uint8_t i;
+    matrix_t denom;
+
+    for (i = 0; i < ref_points_num; i++) {
+        denom =
+            sqrt(
+                pow(
+                    point[0]
+                    - ref_point_matrix[i][0],
+                    2)
+                +
+                pow(
+                    point[1]
+                    - ref_point_matrix[i][1],
+                    2)
+                + pow(
+                    point[2]
+                    - ref_point_matrix[i][2],
+                    2));
+        if (denom != 0) {
+            J[i][0] = (point[0] - ref_point_matrix[i][0]) / denom;
+            J[i][1] = (point[1] - ref_point_matrix[i][1]) / denom;
+            J[i][2] = (point[2] - ref_point_matrix[i][2]) / denom;
+        }
+    }
+}
+
+//compute: J(x)*s
+void dist_based_jacobian_get_J_mul_s(uint8_t ref_points_num,
+                                     matrix_t ref_point_matrix[ref_points_num][3],
+                                     matrix_t point[3], matrix_t s[3],
+                                     matrix_t J_s[ref_points_num])
+{
+    uint8_t i;
+    matrix_t denom;
+    matrix_t j_i_0 = 0;
+    matrix_t j_i_1 = 0;
+    matrix_t j_i_2 = 0;
+
+    for (i = 0; i < ref_points_num; i++) {
+        denom =
+            sqrt(
+                pow(
+                    point[0]
+                    - ref_point_matrix[i][0],
+                    2)
+                +
+                pow(
+                    point[1]
+                    - ref_point_matrix[i][1],
+                    2)
+                + pow(
+                    point[2]
+                    - ref_point_matrix[i][2],
+                    2));
+        if (denom != 0) {
+            j_i_0 = (point[0] - ref_point_matrix[i][0]) / denom;
+            j_i_1 = (point[1] - ref_point_matrix[i][1]) / denom;
+            j_i_2 = (point[2] - ref_point_matrix[i][2]) / denom;
+        }
+        J_s[i] = j_i_0 * s[0] + j_i_1 * s[1] + j_i_2 * s[2];
+    }
+}
diff --git a/localization/position_algos/distance_based/dist_based_position.c b/localization/position_algos/distance_based/dist_based_position.c
new file mode 100644
index 0000000000000000000000000000000000000000..b6f55c9a827cc5015be8a7745db434667af54f3d
--- /dev/null
+++ b/localization/position_algos/distance_based/dist_based_position.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Functions of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include "dist_based_position.h"
+
+#include <math.h>
+
+#include "matrix.h"
+#include "vector.h"
+
+void dist_based_get_absolute_error(matrix_t value_arr[],
+                                   matrix_t approx_value_arr[],
+                                   matrix_t absolute_error_arr[],
+                                   uint8_t length)
+{
+    uint8_t i;
+
+    if ((value_arr != NULL) && (approx_value_arr != NULL)
+        && (absolute_error_arr != NULL)) {
+        for (i = 0; i < length; i++) {
+            absolute_error_arr[i] = fabs(
+                value_arr[i] - approx_value_arr[i]);
+        }
+    }
+}
+
+matrix_t dist_based_get_distance_to_anchor(matrix_t ref_point[3],
+                                           matrix_t point[3])
+{
+    matrix_t dist = 0.0;
+    matrix_t diff_vec[3];
+
+    vector_sub(3, ref_point, point, diff_vec);
+    dist = vector_get_norm2(3, diff_vec);
+
+    return dist;
+}
diff --git a/localization/position_algos/distance_based/doc.txt b/localization/position_algos/distance_based/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30ce964998ba78b38cd94e0ff14d474988e23f74
--- /dev/null
+++ b/localization/position_algos/distance_based/doc.txt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    distance_based DISTANCE_BASED
+ * @ingroup     position_algos
+ *
+ * @brief       localization algorithms of distance-based localization systems.
+ *
+ * @details     The localization module contains functions to compute a position of a mobile device 
+ *              using distance measurements signals. 
+ *
+ * @author      Zakaria Kasmi
+ *
+ */
diff --git a/localization/position_algos/distance_based/include/dist_based_fi.h b/localization/position_algos/distance_based/include/dist_based_fi.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ea19dcf7673927a87066f54dc84cdc34092d3c0
--- /dev/null
+++ b/localization/position_algos/distance_based/include/dist_based_fi.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     distance_based
+ * @{
+ *
+ * @file
+ * @brief       Error function of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#ifndef DIST_BASED_FI_H_
+#define DIST_BASED_FI_H_
+
+#include "matrix.h"
+
+/**
+ * @brief   Defines the error function of a distance-based localization system.
+ * @details This error function is related to one reference station.
+ *
+ * @param[in] point[]           three-dimensional coordinates of the mobile device.
+ * @param[in] ref_point[]       three-dimensional coordinates of a reference station.
+ * @param[in] ri                distance to a reference station.
+ *
+ * @return    the error related to a reference station and destined position.
+ *
+ */
+matrix_t dist_based_fi(matrix_t point[3], matrix_t ref_point[3], matrix_t ri);
+
+/**
+ * @brief   Defines the error function of a distance-based localization system.
+ * @details This error function is related to multiple reference stations.
+ *
+ * @param[in] ref_points_num      Number of the reference stations.
+ * @param[in] ref_point_mat[][]   three-dimensional coordinates of the reference stations.
+ * @param[in] point[]             three-dimensional coordinates of the mobile device.
+ * @param[in] d_vec[]             distances to the reference stations.
+ * @param[out] f_vec[]            errors related to reference stations and destined position.
+ *
+ */
+void dist_based_f_i(uint8_t ref_points_num,
+                    matrix_t ref_point_mat[ref_points_num][3],
+                    matrix_t point[3],
+                    matrix_t d_vec[], matrix_t f_vec[]);
+
+#endif /* DIST_BASED_FI_H_ */
diff --git a/localization/position_algos/distance_based/include/dist_based_jacobian.h b/localization/position_algos/distance_based/include/dist_based_jacobian.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6db03a81c3e4bf8e2881443fed015b1bb4b1c98
--- /dev/null
+++ b/localization/position_algos/distance_based/include/dist_based_jacobian.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     distance_based
+ * @{
+ *
+ * @file
+ * @brief       Jacobian function of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#ifndef DIST_BASED_JACOBIAN_H_
+#define DIST_BASED_JACOBIAN_H_
+
+#include "matrix.h"
+#include "vector.h"
+
+/**
+ * @brief   Defines \f$ J_f^{T} \vec{f} \f$ of distance-based localization system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] dist_vec[]            distances to the reference stations.
+ * @param[in, out] JTf[]            includes the \f$ J_f^{T} \vec{f} \f$ vector.
+ *
+ */
+void dist_based_jacobian_get_JTf(uint8_t ref_points_num,
+                                 matrix_t ref_point_matrix[ref_points_num][3],
+                                 matrix_t point[3],
+                                 matrix_t dist_vec[ref_points_num],
+                                 vector_t JTf[3]);
+
+/**
+ * @brief   Defines \f$ J_f^{T} J_{f} \f$ of distance-based localization
+ *          system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] dist_vec[][]          distances to the reference stations.
+ * @param[out] JTJ[][]              includes the \f$ J_f^{T} J_{f} \f$ matrix.
+ *
+ */
+void dist_based_jacobian_get_JTJ(uint8_t ref_points_num,
+                                 matrix_t ref_point_matrix[ref_points_num][3],
+                                 matrix_t point[3],
+                                 matrix_t dist_vec[ref_points_num],
+                                 matrix_t JTJ[3][3]);
+
+/**
+ * @brief   Computes \f$ J_f^{T} \vec{s} \f$ of distance-based localization system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] s[]                   correction vector.
+ * @param[out] J_s[]                includes the \f$ J_f^{T} \vec{s} \f$ vector.
+ *
+ */
+void dist_based_jacobian_get_J_mul_s(uint8_t ref_points_num,
+                                     matrix_t ref_point_matrix[ref_points_num][3], matrix_t point[3],
+                                     matrix_t s[3], matrix_t J_s[ref_points_num]);
+
+/**
+ * @brief   Computes the Jacobian matrix of distance-based localization system.
+ *
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[out] J[][]                includes the Jacobian Matrix.
+ *
+ */
+void dist_based_jacobian_get_J(uint8_t ref_points_num, matrix_t point[3],
+                               matrix_t ref_point_matrix[ref_points_num][3],
+                               matrix_t J[ref_points_num][3]);
+
+#endif /* DIST_BASED_JACOBIAN_H_ */
diff --git a/localization/position_algos/distance_based/include/dist_based_position.h b/localization/position_algos/distance_based/include/dist_based_position.h
new file mode 100644
index 0000000000000000000000000000000000000000..b48dfaec940d27b0c74c8d61c501ab9be959c6b7
--- /dev/null
+++ b/localization/position_algos/distance_based/include/dist_based_position.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     distance_based
+ * @{
+ *
+ * @file
+ * @brief       Functions of distance-based localization systems.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#ifndef DIST_BASED_POSITION_H_
+#define DIST_BASED_POSITION_H_
+
+#include <math.h>
+#include <inttypes.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Computes the absolute error of a position of a distance-based localization system.
+ *
+ *
+ * @param[in] value_arr[]                 true position.
+ * @param[in] approx_value_arr[]          approximate position of the mobile device.
+ * @param[in, out] absolute_error_arr[]   includes the absolute error.
+ * @param[in] length                      arrays length.
+ *
+ */
+void dist_based_get_absolute_error(matrix_t value_arr[],
+                                   matrix_t approx_value_arr[],
+                                   matrix_t absolute_error_arr[],
+                                   uint8_t length);
+
+/**
+ * @brief   Computes the distance between a mobile station and a reference station
+ *          of a distance-based localization system.
+ *
+ *
+ * @param[in] ref_point   three-dimensional coordinates of the reference stations.
+ * @param[in] point       three-dimensional coordinates of the mobile device.
+ *
+ * @return    the distance between the mobile station and the reference station.
+ */
+matrix_t dist_based_get_distance_to_anchor(matrix_t ref_point[3],
+                                           matrix_t point[3]);
+
+#endif /* DIST_BASED_POSITION_H_ */
diff --git a/localization/position_algos/doc.txt b/localization/position_algos/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b1ae616d2ccdce8e1c8217a748cebe800e93784e
--- /dev/null
+++ b/localization/position_algos/doc.txt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    position_algos POSITION_ALGOS
+ * @ingroup     localization
+ * 
+ * @brief       localization algorithms of distance- and magnetic-based localization systems.
+ *
+ * @details     The localization module contains functions to compute a position of a mobile device 
+ *              using distance measurements or DC-pulsed, magnetic signals.
+ *
+ * @author      Zakaria Kasmi
+ *
+ */
diff --git a/localization/position_algos/magnetic_based/doc.txt b/localization/position_algos/magnetic_based/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..50574fd2981f58e82ceb73ce0ae62d485d67e0b4
--- /dev/null
+++ b/localization/position_algos/magnetic_based/doc.txt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    magnetic_based MAGNETIC_BASED
+ * @ingroup     position_algos
+ *
+ * @brief       localization algorithms of magnetic-based localization systems.
+ *
+ * @details     The localization module contains functions to compute a position of a mobile device 
+ *              using artificially generated DC-pulsed, magnetic signals.
+ *
+ * @author      Zakaria Kasmi
+ *
+ */
diff --git a/localization/position_algos/magnetic_based/include/magnetic_based_fi.h b/localization/position_algos/magnetic_based/include/magnetic_based_fi.h
new file mode 100644
index 0000000000000000000000000000000000000000..26a9de0431931a4eb8962c1182901e820d076911
--- /dev/null
+++ b/localization/position_algos/magnetic_based/include/magnetic_based_fi.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     magnetic_based
+ * @{
+ *
+ * @file
+ * @brief       Error function of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef MAGNETIC_BASED_F_H_
+#define MAGNETIC_BASED_F_H_
+#include <math.h>
+#include <string.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Defines the error function of a magnetic-based localization system.
+ * @details This error function is related to multiple reference stations.
+ *
+ * @param[in] ref_points_num         number of the reference stations.
+ * @param[in] ref_points_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]                three-dimensional coordinates of the mobile device.
+ * @param[in] Bi_vec[]               the measured magnetic field strength.
+ * @param[in, out] f_vec[]           errors related to reference stations and destined position.
+ *
+ */
+void magnetic_based_f_i(uint8_t ref_points_num, matrix_t ref_points_matrix[][3],
+                        matrix_t point[], matrix_t Bi_vec[], matrix_t f_vec[]);
+
+#endif /* MAGNETIC_BASED_F_H_ */
diff --git a/localization/position_algos/magnetic_based/include/magnetic_based_jacobian.h b/localization/position_algos/magnetic_based/include/magnetic_based_jacobian.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d7255f73017648021041d26a566b688df9d7652
--- /dev/null
+++ b/localization/position_algos/magnetic_based/include/magnetic_based_jacobian.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     magnetic_based
+ * @{
+ *
+ * @file
+ * @brief       Jacobian function of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef MAGNETIC_BASED_JACOBIAN_H_
+#define MAGNETIC_BASED_JACOBIAN_H_
+
+#include "matrix.h"
+
+/**
+ * @brief   Computes the Jacobian matrix of magnetic-based localization system.
+ *
+ *
+ * @param[in] ref_point_num         number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in, out] J[][]            includes the Jacobian Matrix.
+ *
+ */
+void magnetic_based_jacobian_get_J(uint8_t ref_point_num,
+                                   matrix_t ref_point_matrix[ref_point_num][3],
+                                   matrix_t point[],
+                                   matrix_t J[ref_point_num][3]);
+
+/**
+ * @brief   Defines \f$ J_f^{T} J_{f} \f$ of magnetic-based localization
+ *          system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] unused                this variable can be set to NULL. It is introduced to guarantee
+ *                                  the compatibility with the @ref dist_based_jacobian_get_JTJ,
+ *                                  @ref modified_gauss_newton, and the @ref opt_levenberg_marquardt
+ *                                  functions.
+ * @param[in, out] JTJ[][]          includes the \f$ J_f^{T} J_{f} \f$ matrix.
+ *
+ */
+void magnetic_based_jacobian_get_JTJ(uint8_t ref_points_num,
+                                     matrix_t ref_point_matrix[ref_points_num][3],
+                                     matrix_t point[3], matrix_t *unused, matrix_t JTJ[3][3]);
+/**
+ * @brief   Defines \f$ J_f^{T} \vec{f} \f$ of magnetic-based localization system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num         number of the reference stations.
+ * @param[in] ref_points_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]                three-dimensional coordinates of the mobile device.
+ * @param[in] Bi_vec[]               magnetic field strengths of the coils (reference stations).
+ * @param[in, out] JTf[]             includes the \f$ J_f^{T} \vec{f} \f$ vector.
+ *
+ */
+void magnetic_based_jacobian_get_JTf(uint8_t ref_points_num,
+                                     matrix_t ref_points_matrix[ref_points_num][3],
+                                     matrix_t point[3], matrix_t Bi_vec[ref_points_num],
+                                     matrix_t JTf[3]);
+
+/**
+ * @brief   Computes \f$ J_f^{T} \vec{s} \f$ of magnetic-based localization system.
+ * @details Where \f$ J_f \f$ is the Jacobian matrix. This function is a part of
+ *          derivatives to minimize the sum of square errors.
+ *
+ * @param[in] ref_points_num        number of the reference stations.
+ * @param[in] ref_point_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] point[]               three-dimensional coordinates of the mobile device.
+ * @param[in] s[]                   correction vector.
+ * @param[in, out] J_s[]            includes the \f$ J_f^{T} \vec{s} \f$ vector.
+ *
+ */
+void magnetic_based_jacobian_get_J_mul_s(uint8_t ref_points_num,
+                                         matrix_t ref_point_matrix[ref_points_num][3],
+                                         matrix_t point[3],
+                                         matrix_t s[3], matrix_t J_s[ref_points_num]);
+
+#endif /* MAGNETIC_BASED_JACOBIAN_H_ */
diff --git a/localization/position_algos/magnetic_based/include/magnetic_based_position.h b/localization/position_algos/magnetic_based/include/magnetic_based_position.h
new file mode 100644
index 0000000000000000000000000000000000000000..2304352531d5855d2b6779f0665d33732175d556
--- /dev/null
+++ b/localization/position_algos/magnetic_based/include/magnetic_based_position.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     magnetic_based
+ * @{
+ *
+ * @file
+ * @brief       Functions of of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#ifndef MAGNETIC_BASED_POSITION_H_
+#define MAGNETIC_BASED_POSITION_H_
+
+#include <inttypes.h>
+#include <math.h>
+
+#include "matrix.h"
+
+/**
+ * The current running through the coil.
+ */
+#define I0         15
+
+/**
+ * The number of turns of the wire.
+ */
+#define NW         140
+
+/**
+ * The radius of the coil.
+ */
+#define R0         0.25
+
+/**
+ * The pi constant.
+ */
+#define PI         3.14159265358979323846
+
+/**
+ * The base area of the coil.
+ */
+#define AR         PI * R0 * R0     //Loop area
+
+/**
+ * The permeability of free space,.
+ */
+#define MU0        4 * PI * 1E-7    //TGm/A
+
+/**
+ * The K constant.
+ */
+#define K          MU0 * NW * I0 * AR / (4 * PI)
+
+/**
+ * From Mega Gauss to Tesla.
+ */
+#define MG_TO_T    1E7
+
+/**
+ * The number of turns of the wire.
+ */
+#define K_T        K * MG_TO_T
+
+/**
+ * The number of turns of the wire.
+ */
+#define MILPS_MAX_DIST     25
+
+/**
+ * @brief   Computes the absolute error of a position of magnet-based localization system.
+ *
+ *
+ * @param[in] value_arr                 true position.
+ * @param[in] approx_value_arr          approximate position of the mobile device.
+ * @param[in, out] absolute_error_arr   includes the absolute error.
+ * @param[in] length                    arrays length.
+ *
+ */
+void magnetic_based_get_absolute_error(matrix_t value_arr[],
+                                       matrix_t approx_value_arr[],
+                                       matrix_t absolute_error_arr[],
+                                       uint8_t length);
+
+/**
+ * @brief   Computes the distances between a mobile station and the reference stations
+ *          of a magnet-based localization system.
+ *
+ *
+ * @param[in] magnetic_field_strength_arr[]   includes the magnetic field strengths.
+ * @param[in] angular_theta_arr[]             elevation angles.
+ * @param[in, out] distance_arr[]             distance array.
+ * @param[in] length                          length of the arrays.
+ * @param[in] k                               magnetic constant.
+ *
+ */
+void magnetic_based_get_distances(matrix_t magnetic_field_strength_arr[],
+                                  matrix_t angular_theta_arr[],
+                                  matrix_t distance_arr[], uint8_t length,
+                                  matrix_t k);
+
+/**
+ * @brief   Computes the distance between a mobile station and a reference stations
+ *          of a magnet-based localization system.
+ *
+ *
+ * @param[in] B       magnetic field strength.
+ * @param[in] theta   elevation angle.
+ * @param[in] k       magnetic constant.
+ *
+ * @return    the distance between the mobile station and the reference station.
+ */
+matrix_t magnetic_based_get_r(matrix_t B, matrix_t theta, matrix_t k);
+
+/**
+ * @brief   Computes the distance between a mobile station and a reference station
+ *          of magnetic-based localization system.
+ *
+ *
+ * @param[in] ref_point[]   three-dimensional coordinates of the reference stations.
+ * @param[in] point[]       three-dimensional coordinates of the mobile device.
+ *
+ * @return    the distance between the mobile station and the reference station.
+ */
+matrix_t magnetic_based_get_distances_to_anchors(matrix_t ref_point[3],
+                                                 matrix_t point[3]);
+/**
+ * @brief   Computes the magnetic field strength from a mobile station to a reference station.
+ *
+ *
+ * @param[in] ref_point[]     three-dimensional coordinates of a reference station.
+ * @param[in] target_point[]  three-dimensional coordinates of the mobile device.
+ * @param[in] k               magnetic constant.
+ *
+ * @return    the magnetic field strength.
+ */
+matrix_t magnetic_based_get_magnetic_field(matrix_t ref_point[3],
+                                           matrix_t target_point[3],
+                                           matrix_t k);
+/**
+ * @brief   Computes the magnetic field strengths from a mobile station to various reference
+ *          stations.
+ *
+ * @param[in] m                         number of the reference stations.
+ * @param[in] ref_point_matrix[][]      three-dimensional coordinates of the reference stations.
+ * @param[in] target_point[]            three-dimensional coordinates of the mobile device.
+ * @param[in] k                         magnetic constant.
+ * @param[in, out] magn_field_vec[]     includes the magnetic field strengths.
+ *
+ */
+void magnetic_based_get_magnetic_field_vec(uint8_t m,
+                                           matrix_t ref_point_matrix[m][3],
+                                           matrix_t target_point[],
+                                           matrix_t k,
+                                           matrix_t magn_field_vec[]);
+
+/**
+ * @brief     Computes the position of a mobile station by a magnetic-based localization system.
+ * @details   The position is computed based on a pre-processed pseudo-inverse matrix and the
+ *            homogeneous solution in the case of three reference stations.
+ *
+ * @param[in] anchor_num                        number of the reference stations.
+ * @param[in] anchor_pos_matrix[][]             coordinates of the reference stations.
+ * @param[in] pseudo_inv_matrix[][[]            pointer to the pre-processed pseudo-inverse matrix.
+ * @param[in] homog_sol_arr[]                   pointer to the homogeneous solution.
+ * @param[in, out] solution_x1[]                  includes the first solution.
+ * @param[in, out] solution_x2[]                  includes the second solution.
+ *
+ */
+void magnetic_based_preprocessing_get_position(uint8_t anchor_num,
+                                               matrix_t anchor_pos_matrix[anchor_num][3],
+                                               matrix_t pseudo_inv_matrix[4][anchor_num],
+                                               matrix_t homog_sol_arr[],
+                                               matrix_t solution_x1[],
+                                               matrix_t solution_x2[]);
+
+#endif /* MAGNETIC_BASED_POSITION_H_ */
diff --git a/localization/position_algos/magnetic_based/magnetic_based_fi.c b/localization/position_algos/magnetic_based/magnetic_based_fi.c
new file mode 100644
index 0000000000000000000000000000000000000000..a8afbc39a8b173ec083ce7535bc42353d34915d2
--- /dev/null
+++ b/localization/position_algos/magnetic_based/magnetic_based_fi.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Error function of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <math.h>
+#include <inttypes.h>
+#include <magnetic_based_position.h>
+
+#include "matrix.h"
+
+void magnetic_based_f_i(uint8_t ref_points_num,
+                        matrix_t ref_points_matrix[][3], matrix_t point[],
+                        matrix_t Bi_vec[], matrix_t f_vec[])
+{
+
+    for (int i = 0; i < ref_points_num; i++) {
+
+        matrix_t X_Xi_sq = pow(point[0] - ref_points_matrix[i][0], 2);
+        matrix_t Y_Yi_sq = pow(point[1] - ref_points_matrix[i][1], 2);
+        matrix_t Z_Zi_sq = pow(point[2] - ref_points_matrix[i][2], 2);
+
+        f_vec[i] = (K_T * (sqrt(X_Xi_sq + Y_Yi_sq + 4.0 * Z_Zi_sq)) /
+                    pow((X_Xi_sq + Y_Yi_sq + Z_Zi_sq), 2))
+                   - Bi_vec[i];
+    }
+}
diff --git a/localization/position_algos/magnetic_based/magnetic_based_jacobian.c b/localization/position_algos/magnetic_based/magnetic_based_jacobian.c
new file mode 100644
index 0000000000000000000000000000000000000000..35f19bfe828b4a2ef47a6d17d9f28f5949681089
--- /dev/null
+++ b/localization/position_algos/magnetic_based/magnetic_based_jacobian.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Jacobian function of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "magnetic_based_fi.h"
+#include "magnetic_based_position.h"
+#include "matrix.h"
+
+void magnetic_based_jacobian_get_J(uint8_t ref_point_num,
+                                   matrix_t ref_point_matrix[ref_point_num][3],
+                                   matrix_t point[],
+                                   matrix_t J[ref_point_num][3])
+{
+
+    for (int i = 0; i < ref_point_num; i++) {
+
+        matrix_t X_Xi = point[0] - ref_point_matrix[i][0];
+        matrix_t Y_Yi = point[1] - ref_point_matrix[i][1];
+        matrix_t Z_Zi = point[2] - ref_point_matrix[i][2];
+
+        matrix_t X_Xi_sq = pow(X_Xi, 2);
+        matrix_t Y_Yi_sq = pow(Y_Yi, 2);
+        matrix_t Z_Zi_sq = pow(Z_Zi, 2);
+
+        J[i][0] =
+            K_T * (X_Xi)
+            * ((-3.0 * X_Xi_sq
+                - 3.0 * Y_Yi_sq
+                - 15.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+
+        J[i][1] =
+            K_T * (Y_Yi)
+            * ((-3.0 * X_Xi_sq
+                - 3.0 * Y_Yi_sq
+                - 15.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+
+        J[i][2] =
+            4.0 * K_T * (Z_Zi)
+            * ((-3.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+    }
+}
+
+void magnetic_based_jacobian_get_JTJ(uint8_t ref_points_num,
+                                     matrix_t ref_point_matrix[ref_points_num][3],
+                                     matrix_t point[3], matrix_t *unused, matrix_t JTJ[3][3])
+{
+    matrix_t J[ref_points_num][3];
+
+    magnetic_based_jacobian_get_J(ref_points_num, ref_point_matrix, point,
+                                  J);
+    matrix_trans_mul_itself(ref_points_num, 3, J, JTJ);
+
+    (void)unused;
+}
+
+void magnetic_based_jacobian_get_JTf(uint8_t ref_points_num,
+                                     matrix_t ref_points_matrix[ref_points_num][3],
+                                     matrix_t point[3], matrix_t Bi_vec[ref_points_num],
+                                     matrix_t JTf[3])
+{
+
+    matrix_t J[ref_points_num][3];
+    matrix_t f_vec[ref_points_num];
+
+    magnetic_based_f_i(ref_points_num, ref_points_matrix, point, Bi_vec,
+                       f_vec);
+
+    magnetic_based_jacobian_get_J(ref_points_num, ref_points_matrix, point,
+                                  J);
+    matrix_trans_mul_vec(ref_points_num, 3, J, ref_points_num, f_vec, JTf);
+}
+
+//compute: J(x)*s
+void magnetic_based_jacobian_get_J_mul_s(uint8_t ref_points_num,
+                                         matrix_t ref_point_matrix[ref_points_num][3],
+                                         matrix_t point[3],
+                                         matrix_t s[3],
+                                         matrix_t J_s[ref_points_num])
+{
+    uint8_t i;
+    matrix_t X_Xi, Y_Yi, Z_Zi;
+    matrix_t X_Xi_sq, Y_Yi_sq, Z_Zi_sq;
+    matrix_t j_i_0, j_i_1, j_i_2;
+
+    for (i = 0; i < ref_points_num; i++) {
+        X_Xi = point[0] - ref_point_matrix[i][0];
+        Y_Yi = point[1] - ref_point_matrix[i][1];
+        Z_Zi = point[2] - ref_point_matrix[i][2];
+
+        X_Xi_sq = pow(X_Xi, 2);
+        Y_Yi_sq = pow(Y_Yi, 2);
+        Z_Zi_sq = pow(Z_Zi, 2);
+
+        j_i_0 =
+            K_T * (X_Xi)
+            * ((-3.0 * X_Xi_sq
+                - 3.0 * Y_Yi_sq
+                - 15.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+        j_i_1 =
+            K_T * (Y_Yi)
+            * ((-3.0 * X_Xi_sq
+                - 3.0 * Y_Yi_sq
+                - 15.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+        j_i_2 =
+            4.0 * K_T * (Z_Zi)
+            * ((-3.0 * Z_Zi_sq)
+               /
+               (sqrt(
+                    X_Xi_sq
+                    + Y_Yi_sq
+                    + 4.0
+                    * Z_Zi_sq)
+                * pow(
+                    (X_Xi_sq
+                     + Y_Yi_sq
+                     + Z_Zi_sq),
+                    3)));
+
+        J_s[i] = j_i_0 * s[0] + j_i_1 * s[1] + j_i_2 * s[2];
+    }
+}
diff --git a/localization/position_algos/magnetic_based/magnetic_based_position.c b/localization/position_algos/magnetic_based/magnetic_based_position.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cca048ece5cdd847418fff40675a935d0ac8ddd
--- /dev/null
+++ b/localization/position_algos/magnetic_based/magnetic_based_position.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Functions of of DC-pulsed, magnetic localization system.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#include <math.h>
+#include <complex.h>
+#include <magnetic_based_position.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "matrix.h"
+#include "vector.h"
+#include "trilateration.h"
+
+void magnetic_based_get_absolute_error(matrix_t value_arr[],
+                                       matrix_t approx_value_arr[],
+                                       matrix_t absolute_error_arr[],
+                                       uint8_t length)
+{
+    uint8_t i;
+
+    if ((value_arr != NULL) && (approx_value_arr != NULL)
+        && (absolute_error_arr != NULL)) {
+        for (i = 0; i < length; i++) {
+            absolute_error_arr[i] = fabs(
+                value_arr[i] - approx_value_arr[i]);
+        }
+    }
+}
+
+matrix_t magnetic_based_get_distances_to_anchors(matrix_t ref_point[3],
+                                                 matrix_t point[3])
+{
+    matrix_t dist = 0.0;
+    matrix_t diff_vec[3];
+
+    vector_sub(3, ref_point, point, diff_vec);
+    dist = vector_get_norm2(3, diff_vec);
+
+    return dist;
+}
+
+matrix_t magnetic_based_get_magnetic_field(matrix_t ref_point[3],
+                                           matrix_t target_point[3], matrix_t k)
+{
+    matrix_t magn_field = 0.0;
+    matrix_t r_square = 0.0;
+    uint8_t i;
+
+    printf("ref_arr = ");
+    vector_flex_print(3, ref_point, 5, 4);
+    puts("");
+    for (i = 0; i < 3; i++) {
+        r_square += pow(target_point[i] - ref_point[i], 2);
+    }
+
+    printf("r_sq = %f\n", r_square);
+    magn_field =
+        k
+        * sqrt(
+            3
+            * pow(
+                target_point[2]
+                - ref_point[2],
+                2)
+            + r_square)
+        / pow(r_square, 2);
+
+    return magn_field;
+}
+
+void magnetic_based_get_magnetic_field_vec(uint8_t m,
+                                           matrix_t ref_point_matrix[m][3],
+                                           matrix_t target_point[],
+                                           matrix_t k,
+                                           matrix_t magn_field_vec[])
+{
+
+    matrix_t r_square = 0.0;
+    uint8_t i, j;
+
+    for (i = 0; i < m; i++) {
+        for (j = 0; i < 3; j++) {
+            r_square +=
+                pow(
+                    target_point[i]
+                    - ref_point_matrix[i][j],
+                    2);
+        }
+
+        magn_field_vec[i] =
+            k
+            * sqrt(
+                3
+                * pow(
+                    target_point[2]
+                    - ref_point_matrix[i][2],
+                    2)
+                + r_square)
+            / pow(r_square, 2);
+        r_square = 0.0;
+    }
+}
+
+
+void magnetic_based_get_distances(matrix_t magnetic_field_strength_arr[],
+                                  matrix_t angular_theta_arr[],
+                                  matrix_t distance_arr[], uint8_t length,
+                                  matrix_t k)
+{
+    int i;
+
+    for (i = 0; i < length; i++) {
+        if (magnetic_field_strength_arr[i] == 0) {
+            distance_arr[i] = MILPS_MAX_DIST;
+        }
+        else {
+            if (angular_theta_arr[i] == 0) {
+                distance_arr[i] =
+                    pow(
+                        k
+                        / magnetic_field_strength_arr[i],
+                        (matrix_t)1
+                        / 3);
+            }
+            else {
+
+                distance_arr[i] =
+                    pow(
+                        k
+                        * sqrt(
+                            1
+                            + 3
+                            * pow(
+                                sin(
+                                    angular_theta_arr[i]),
+                                2))
+                        / magnetic_field_strength_arr[i],
+                        (matrix_t)1
+                        / 3);
+            }
+        }
+    }
+}
+
+
+matrix_t magnetic_based_get_r(matrix_t B, matrix_t theta, matrix_t k)
+{
+    matrix_t r = 0;
+
+    if (B == 0) {
+        return MILPS_MAX_DIST;
+    }
+    else {
+        if (theta == 0) {
+            r = pow(k / B, (matrix_t)1 / 3);
+        }
+        else {
+
+            r = pow(k * sqrt(1 + 3 * pow(sin(theta), 2)) / B,
+                    (matrix_t)1 / 3);
+        }
+    }
+
+    return r;
+}
+
+// PC proprocessing
+void magnetic_based_preprocessing_get_position(uint8_t anchor_num,
+                                               matrix_t anchor_pos_matrix[anchor_num][3],
+                                               matrix_t pseudo_inv_matrix[4][anchor_num],
+                                               matrix_t homog_sol_arr[],
+                                               matrix_t solution_x1[],
+                                               matrix_t solution_x2[])
+{
+
+    matrix_t dist_arr[anchor_num];
+
+    trilateration1(anchor_num, anchor_pos_matrix, pseudo_inv_matrix,
+                   homog_sol_arr, dist_arr, solution_x1, solution_x2);
+
+}
diff --git a/localization/position_algos/pos_algos_common/DOP.c b/localization/position_algos/pos_algos_common/DOP.c
new file mode 100644
index 0000000000000000000000000000000000000000..e60588e74281877e0f31401d32c5dbe8a2ac9e5c
--- /dev/null
+++ b/localization/position_algos/pos_algos_common/DOP.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Compute the Position Dilution of Precision (PDOP).
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <math.h>
+
+#include "DOP.h"
+
+#include "moore_penrose_pseudo_inverse.h"
+#include "matrix.h"
+
+matrix_t get_PDOP(uint8_t m, matrix_t ref_Matrix[m][3],
+                  matrix_t true_pos[m])
+{
+
+    matrix_t PDOP = 0.0;
+    matrix_t H[m][4];
+    matrix_t H_transpose[4][m];
+    matrix_t H_transpose_H[4][4];
+    matrix_t H_transpose_H_pinv[4][4];
+
+    for (int i = 0; i < m; i++) {
+        matrix_t R_i = sqrt(pow(ref_Matrix[i][0] - true_pos[0], 2)
+                            + pow(ref_Matrix[i][1] - true_pos[1], 2)
+                            + pow(ref_Matrix[i][2] - true_pos[2], 2));
+
+        for (int l = 0; l < 3; l++) {
+            H[i][l] = (ref_Matrix[i][l] - true_pos[l]) / R_i;
+        }
+        H[i][3] = -1;
+    }
+
+    matrix_transpose(m, 4, H, H_transpose);
+    matrix_mul(4, m, H_transpose, m, 4, H, H_transpose_H);
+    moore_penrose_get_pinv(4, 4, H_transpose_H, H_transpose_H_pinv);
+
+    for (int i = 0; i < 3; i++) {
+        PDOP = PDOP + H_transpose_H_pinv[i][i];
+    }
+    PDOP = sqrt(PDOP);
+    return PDOP;
+}
diff --git a/localization/position_algos/pos_algos_common/doc.txt b/localization/position_algos/pos_algos_common/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b8257c30c5def97efbe0085af66763b06c560312
--- /dev/null
+++ b/localization/position_algos/pos_algos_common/doc.txt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    pos_algos_common POS_ALGOS_COMMON
+ * @ingroup     position_algos
+ *
+ * @brief       Common algorithms of localization systems.
+ *
+ * @details This module contains common functions such as the trilateration or the Position Dilution
+ *           of Precision (PDOP).
+ *          
+ * @author      Zakaria Kasmi
+ *
+ */
diff --git a/localization/position_algos/pos_algos_common/include/DOP.h b/localization/position_algos/pos_algos_common/include/DOP.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b4f1e90d1846285c0e2b1a2b7aa114824cc0332
--- /dev/null
+++ b/localization/position_algos/pos_algos_common/include/DOP.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     pos_algos_common
+ * @{
+ *
+ * @file
+ * @brief       Compute the Position Dilution of Precision (PDOP).
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef DOP_H_
+#define DOP_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Compute the Position Dilution of Precision (PDOP).
+ *
+ * @param[in] m                 number of the reference stations.
+ * @param[in] ref_Matrix        three-dimensional coordinates of the reference stations.
+ * @param[in] true_pos          three-dimensional coordinates of the mobile device.
+ *
+ *
+ * @return    the PDOP-value.
+ *
+ */
+matrix_t get_PDOP(uint8_t m, matrix_t ref_Matrix[m][3], matrix_t true_pos[m]);
+
+#endif /* DOP_H_ */
diff --git a/localization/position_algos/pos_algos_common/include/trilateration.h b/localization/position_algos/pos_algos_common/include/trilateration.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb9c787f06670da6ac3957ded8c71ccd4544e509
--- /dev/null
+++ b/localization/position_algos/pos_algos_common/include/trilateration.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     pos_algos_common
+ * @{
+ *
+ * @file
+ * @brief       Implement the trilateration algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#ifndef TRILATERATION_H_
+#define TRILATERATION_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Implement the trilateration algorithm using the pre-processed pseudo-inverse matrix.
+ * @note    This function should be initialized with the pre-processed pseudo-inverse matrix of
+ *          the equation system: \f$ A \vec{x} = 0 \f$.
+ *          Caution!: The \p solution_x1 and the \p solution_x2 vectors have a length of 3 or 4 in
+ *          the case of two-dimensional or three-dimensional space. The first element \f$(x_0)\f$
+ *          of the \p solution_x1[] and the \p solution_x2[] vectors is a measure of the solvability
+ *          of the multilateration problem. For example, in the three-dimensional space:
+ *          \f$ d =  x_0 - \left( x_1^{2} + x_2^{2} + x_3^{2} \right)\f$.
+ *
+ *
+ * @param[in] anchor_num              number of the reference stations.
+ * @param[in] anchor_pos_matrix[][]   three-dimensional coordinates of the reference stations.
+ * @param[in] pseudo_inv_matrix[][]   pointer to the pre-processed pseudo-inverse matrix.
+ * @param[in] homog_sol_arr[]         the homogeneous solution.
+ * @param[in] dist_arr[]              distances to the reference stations.
+ * @param[in, out] solution_x1[]      includes the first solution. It has the length of 3 or 4 in
+ *                                    the case of two-dimensional or three-dimensional space.
+ * @param[in, out] solution_x2[]      includes the second solution. It has length of 3 or 4 in the
+ *                                    case of two-dimensional or three-dimensional space.
+ *
+ */
+void trilateration1(uint8_t anchor_num,
+                    matrix_t anchor_pos_matrix[anchor_num][3],
+                    matrix_t pseudo_inv_matrix[4][anchor_num],
+                    matrix_t homog_sol_arr[],
+                    matrix_t dist_arr[],
+                    matrix_t solution_x1[],
+                    matrix_t solution_x2[]
+                    );
+
+/**
+ * @brief   Implement the trilateration algorithm.
+ * @note    The pre-processed pseudo-inverse matrix of the equation system:
+ *          \f$ A \vec{x} = 0 \f$ is computed on the mobile station.
+ *          Caution!: The \p solution_x1 and the \p solution_x2 vectors have a length of 3 or 4 in
+ *          the case of two-dimensional or three-dimensional space. The first element \f$(x_0)\f$
+ *          of the \p solution_x1[] and the \p solution_x2[] vectors is a measure of the solvability
+ *          of the multilateration problem. For example, in the three-dimensional space:
+ *          \f$ d =  x_0 - \left( x_1^{2} + x_2^{2} + x_3^{2} \right)\f$.
+ *
+ * @param[in] anchor_num             number of the reference stations.
+ * @param[in] anchor_pos_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] dist_arr[]             distances to the reference stations.
+ * @param[in, out] solution_x1[]     includes the first solution. It has the length of 3 or 4 in
+ *                                   the case of two-dimensional or three-dimensional space.
+ * @param[in, out] solution_x2[]     includes the second solution. It has the length of 3 or 4 in
+ *                                   the case of two-dimensional or three-dimensional space.
+ *
+ */
+void trilateration2(uint8_t anchor_num,
+                    matrix_t anchor_pos_matrix[anchor_num][3],
+                    matrix_t dist_arr[],
+                    matrix_t solution_x1[],
+                    matrix_t solution_x2[]);
+
+/**
+ * @brief   Computes the matrix \f$ A \f$ of the equation system:
+ *          \f$ A \vec{x} = \vec{b}\f$.
+ *
+ * @param[in] m                         number of the reference stations.
+ * @param[in] anchor_pos_matrix[][]     three-dimensional coordinates of the reference stations.
+ * @param[in, out] A_matrix[][]         pointer to the matrix \f$ A \f$.
+ *
+ */
+void trilateration_get_A_matrix(uint8_t m, matrix_t anchor_pos_matrix[m][3],
+                                matrix_t A_matrix[m][4]);
+/**
+ * @brief   Computes the vector \f$ \vec{b} \f$ of the equation system:
+ *          \f$ A \vec{x} = \vec{b}\f$.
+ *
+ * @param[in] anchor_num                number of the reference stations.
+ * @param[in] dist_arr[]                distances to the reference stations.
+ * @param[in] anchor_pos_matrix[][]     three-dimensional coordinates of the reference stations.
+ * @param[in, out] b_vec[]              pointer to the vector \f$ vec{b} \f$.
+ *
+ */
+void trilateration_get_b_vector(uint8_t anchor_num, matrix_t dist_arr[],
+                                matrix_t anchor_pos_matrix[anchor_num][3],
+                                matrix_t b_vec[]);
+
+/**
+ * @brief   Compute the particular solution, which is the general solution of
+ *          \f$ A \vec{x_0} = \vec{b_0}\f$.
+ * @note    The particular solution is calculated in the case of three reference stations.
+ *          The particular solution is computed using the pre-processed pseudo-inverse matrix.
+ *
+ * @param[in] pseudo_inv_matrix[][]        pointer to the pre-processed pseudo-inverse matrix.
+ * @param[in] b_arr[]                      pointer the vector \f$ vec{b} \f$.
+ * @param[in, out] particular_solu_arr[]   includes the particular solution.
+ *
+ */
+void trilateration_preprocessed_get_particular_solution(
+    matrix_t pseudo_inv_matrix[4][3],
+    matrix_t b_arr[],
+    matrix_t particular_solu_arr[]);
+
+/**
+ * @brief   Compute the particular solution, which is the general solution of
+ *          \f$ A \vec{x_0} = \vec{b_0} \f$.
+ * @note    The particular solution is calculated in the case of three reference stations.
+ *          The particular solution is computed on the mobile station.
+ *
+ * @param[in] m                    number of the reference stations.
+ * @param[in] n                    column number of the reference stations matrix.
+ * @param[in] anchor_pos_mat[][]   three-dimensional coordinates of the reference stations.
+ * @param[in] dist_arr[]           distances to the reference stations.
+ * @param[in, out] Xp[]            includes the particular solution.
+ */
+void trilateration_get_particular_solution(uint8_t m, uint8_t n,
+                                           matrix_t anchor_pos_mat[m][n],
+                                           matrix_t dist_arr[], matrix_t Xp[]);
+
+/**
+ * @brief   Compute the rank and the solution of the homogeneous system
+ *          \f$ A \vec{x_0} = 0 \f$.
+ *
+ * @param[in] anchor_num              number of the reference stations.
+ * @param[in] anchor_pos_matrix[][]   three-dimensional coordinates of the reference stations.
+ * @param[in, out] Xh[]               includes the homogeneous solution.
+ *
+ * @return  the rank of the matrix \f$ A \f$.
+ */
+uint8_t trilateration_get_rank_and_homogeneous_solution(uint8_t anchor_num,
+                                                        matrix_t anchor_pos_matrix[anchor_num][3],
+                                                        matrix_t Xh[]);
+/**
+ * @brief    Solve a quadratic equation.
+ * @details  The quotients of the quadratic equation are derived from the particular and homogeneous
+ *           solution.
+ *
+ * @param[in] particular_solu_arr[]        pointer to the particular solution.
+ * @param[in] homogeneous_solution_arr[]   pointer to the homogeneous solution.
+ * @param[in, out] solution_x1[]           presents the first solution.
+ * @param[in, out] solution_x2[]           presents the second solution.
+ *
+ */
+void trilateration_get_quadratic_equation_solution(
+    matrix_t particular_solu_arr[],
+    matrix_t homogeneous_solution_arr[],
+    matrix_t solution_x1[],
+    matrix_t solution_x2[]);
+
+/**
+ * @brief    Solve a linear equation.
+ * @details  The linear equation is solved by using the pre-processed pseudo-inverse matrix and the
+ *           vector \f$ \vec{b} \f$
+ *
+ * @param[in] line_num               row number of the pseudo-inverse matrix.
+ * @param[in] col_num                column number of the pseudo-inverse matrix.
+ * @param[in] pseudo_inv_matrix[][]  pointer to the pre-processed pseudo-inverse matrix.
+ * @param[in] b_vec[]                pointer to the vector \f$ \vec{b} \f$.
+ * @param[out] sol_vec[]             solution vector.
+ *
+ */
+void trilateration_solve_linear_equation(uint8_t line_num, uint8_t col_num,
+                                         matrix_t pseudo_inv_matrix[line_num][col_num],
+                                         matrix_t b_vec[], matrix_t sol_vec[]);
+
+#endif /* TRILATERATION_H_ */
diff --git a/localization/position_algos/pos_algos_common/trilateration.c b/localization/position_algos/pos_algos_common/trilateration.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fe95707c6b295938933af6c3c2a34bcd2278f6a
--- /dev/null
+++ b/localization/position_algos/pos_algos_common/trilateration.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the trilateration algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "moore_penrose_pseudo_inverse.h"
+#include "matrix.h"
+#include "svd.h"
+#include "trilateration.h"
+
+void trilateration1(uint8_t anchor_num,
+                    matrix_t anchor_pos_matrix[anchor_num][3],
+                    matrix_t pseudo_inv_matrix[4][anchor_num],
+                    matrix_t homog_sol_arr[],
+                    matrix_t dist_arr[],
+                    matrix_t solution_x1[],
+                    matrix_t solution_x2[]
+                    )
+{
+
+    matrix_t b_arr[anchor_num];
+    matrix_t particular_solution_arr[4];
+
+    if (anchor_num == 3) {
+        trilateration_get_b_vector(anchor_num, dist_arr,
+                                   anchor_pos_matrix, b_arr);
+        trilateration_preprocessed_get_particular_solution(
+            pseudo_inv_matrix, b_arr,
+            particular_solution_arr);
+        trilateration_get_quadratic_equation_solution(
+            particular_solution_arr,
+            homog_sol_arr, solution_x1, solution_x2);
+
+    }
+
+    else if (anchor_num > 3) {
+        trilateration_get_b_vector(anchor_num, dist_arr,
+                                   anchor_pos_matrix, b_arr);
+
+        //compute the solution
+        trilateration_solve_linear_equation(anchor_num, anchor_num,
+                                            pseudo_inv_matrix, b_arr,
+                                            solution_x1);
+    }
+}
+
+//On MCU Processing
+void trilateration2(uint8_t anchor_num,
+                    matrix_t anchor_pos_matrix[anchor_num][3],
+                    matrix_t dist_arr[],
+                    matrix_t solution_x1[],
+                    matrix_t solution_x2[])
+{
+
+    matrix_t b_arr[anchor_num];
+    matrix_t A_matrix[anchor_num][4];
+    matrix_t pseudo_inv_matrix[4][anchor_num];
+    uint8_t rank = 0;
+
+    if (anchor_num == 3) {
+        //2nd compute the particular solution
+        matrix_t Xp[4];
+        trilateration_get_particular_solution(anchor_num, anchor_num,
+                                              anchor_pos_matrix, dist_arr, Xp);
+
+        //3th compute the homogeneous solution
+        matrix_t Xh[4];
+        rank = trilateration_get_rank_and_homogeneous_solution(
+            anchor_num, anchor_pos_matrix, Xh);
+
+        //solve the quadratic equation
+        if (rank == 3) {
+            trilateration_get_quadratic_equation_solution(Xp, Xh,
+                                                          solution_x1,
+                                                          solution_x2);
+        }
+        else {
+            puts("rank!=3, the equation system is not solvable.");
+        }
+
+    }
+
+    else if (anchor_num > 3) {
+        //compute A-matrix and b_vector
+        trilateration_get_A_matrix(anchor_num, anchor_pos_matrix,
+                                   A_matrix);
+        trilateration_get_b_vector(anchor_num, dist_arr,
+                                   anchor_pos_matrix, b_arr);
+
+        //compute the pseudo inverse
+        moore_penrose_get_pinv(anchor_num, 4, A_matrix,
+                               pseudo_inv_matrix);
+        //compute the solution
+        trilateration_solve_linear_equation(4, anchor_num,
+                                            pseudo_inv_matrix, b_arr,
+                                            solution_x1);
+    }
+}
+
+void trilateration_preprocessed_get_particular_solution(
+    matrix_t pseudo_inv_matrix[4][3],
+    matrix_t b_arr[],
+    matrix_t particular_solu_arr[])
+{
+    int i = 0;
+    int j = 0;
+
+    memset(particular_solu_arr, 0.0, 4 * sizeof(matrix_t));
+
+    for (; i < 4; i++) {
+        for (; j < 3; j++) {
+            particular_solu_arr[i] += pseudo_inv_matrix[i][j]
+                                      * b_arr[j];
+            //DEBUGF("pseudo_inv_matrix[%d][%d]  = %f\n b_arr[%d] = %f\n", i, j, (double) pseudo_inv_matrix[i][j], j, (double) b_arr[j]);
+            //printf("pseudo_inv_matrix[%d][%d]  = %f\n b_arr[%d] = %f\n", i, j, (double) pseudo_inv_matrix[i][j], j, (double) b_arr[j]);
+        }
+        j = 0;
+    }
+#ifdef DEBUG_ENABLED
+    i = 0;
+    for (; i < 4; i++) {
+        DEBUGF("particular_solution_arr[%d] = %f\n", i,
+               (double)particular_solu_arr[i]);
+    }
+#endif
+}
+
+uint8_t trilateration_get_rank_and_homogeneous_solution(uint8_t anchor_num,
+                                                        matrix_t anchor_pos_matrix[anchor_num][3],
+                                                        matrix_t Xh[])
+{
+    uint8_t rank = 0;
+    matrix_t A[anchor_num][4];
+    uint8_t m = anchor_num;
+    uint8_t n = 4;
+    uint8_t s_length = svd_get_single_values_num(m, n);
+    matrix_t s[s_length];
+    matrix_dim_t u_dim;
+
+    svd_get_U_dim(m, n, &u_dim);
+    matrix_t U[u_dim.row_num][u_dim.col_num];
+    matrix_t S[u_dim.col_num][n];
+    matrix_t V[n][n];
+
+    trilateration_get_A_matrix(anchor_num, anchor_pos_matrix, A);
+    svd(m, n, A, u_dim.row_num, u_dim.col_num, U, S, V, s_length, s);
+
+    //the forth column of the V matix
+    for (int i = 0; i < n; i++) {
+        Xh[i] = V[i][3];
+    }
+
+    rank = matrix_get_rank(m, n, s, s_length);
+
+    return rank;
+}
+
+void trilateration_get_particular_solution(uint8_t m, uint8_t n,
+                                           matrix_t anchor_pos_mat[m][n],
+                                           matrix_t dist_arr[], matrix_t Xp[])
+{
+    matrix_t A[m][4];
+    matrix_t pinvA[4][m];
+    matrix_t b[m];
+
+    trilateration_get_b_vector(m, dist_arr, anchor_pos_mat, b);
+    trilateration_get_A_matrix(m, anchor_pos_mat, A);
+    moore_penrose_get_pinv(m, 4, A, pinvA);
+    matrix_mul_vec(4, m, pinvA, b, Xp);
+}
+
+void trilateration_get_quadratic_equation_solution(matrix_t Xp[],
+                                                   matrix_t Xh[],
+                                                   matrix_t solution_x1[],
+                                                   matrix_t solution_x2[])
+{
+
+    matrix_t a = 0, b = 0, c = 0, t1 = 0, t2 = 0, delta = 0;
+    int i = 0;
+
+    //compute polynomial coefficients: a*t^2 + b*t^+ c
+    a = pow(Xh[1], 2)
+        + pow(Xh[2], 2)
+        + pow(Xh[3], 2);
+    b = 2
+        * (Xh[1] * Xp[1]
+           + Xh[2] * Xp[2]
+           + Xh[3] * Xp[3])
+        - Xh[0];
+    c = pow(Xp[1], 2) + pow(Xp[2], 2)
+        + pow(Xp[3], 2) - Xp[0];
+
+    //compute the quadratic equation a*t^2 + b*t+ c
+    delta = b * b - 4 * a * c;
+    if ((delta > 0) && (a != 0)) {
+        if (solution_x1 != NULL) {
+            t1 = (-b + sqrt(delta)) / (2 * a);
+        }
+        if (solution_x2 != NULL) {
+            t2 = (-b - sqrt(delta)) / (2 * a);
+        }
+    }
+    else if ((delta == 0) && (a != 0)) {
+        if (solution_x1 != NULL) {
+            t1 = -b / (2 * a);
+        }
+        if (solution_x2 != NULL) {
+            t2 = t1;
+        }
+
+    }
+    else if (delta < 0) {   // take only a real part
+        if (solution_x1 != NULL) {
+            t1 = -b / (2 * a);
+        }
+        if (solution_x2 != NULL) {
+            t2 = -b / (2 * a);
+        }
+    }
+
+    for (; i < 4; i++) {
+        if (solution_x1 != NULL) {
+            solution_x1[i] = Xp[i]
+                             + t1 * Xh[i];
+        }
+        if (solution_x2 != NULL) {
+            solution_x2[i] = Xp[i]
+                             + t2 * Xh[i];
+        }
+    }
+
+    //DEBUGF("a=%f, b=%f, c=%f, t1=%f, t2=%f\n", (double)a, (double)b, (double)c, (double)t1, (double)t2);
+}
+
+void trilateration_get_A_matrix(uint8_t m, matrix_t anchor_pos_matrix[m][3],
+                                matrix_t A_matrix[m][4])
+{
+    int i, j;
+
+    //the first column is equal 1
+    for (i = 0; i < m; i++) {
+        A_matrix[i][0] = 1;
+    }
+
+    //the second, third and firth columns are equal: -2x, -2y, -2z respectively
+    for (i = 0; i < m; i++) {
+        for (j = 1; j < 4; j++) {
+            A_matrix[i][j] = -2 * anchor_pos_matrix[i][j - 1];
+
+        }
+    }
+}
+
+void trilateration_get_b_vector(uint8_t anchor_num, matrix_t dist_arr[],
+                                matrix_t anchor_pos_matrix[anchor_num][3],
+                                matrix_t b_vec[])
+{
+
+    uint8_t i, j;
+
+    for (i = 0; i < anchor_num; i++) {
+        b_vec[i] = dist_arr[i] * dist_arr[i];
+        for (j = 0; j < 3; j++) {
+            b_vec[i] -= anchor_pos_matrix[i][j]
+                        * anchor_pos_matrix[i][j];
+        }
+    }
+}
+
+void trilateration_solve_linear_equation(uint8_t line_num, uint8_t col_num,
+                                         matrix_t pseudo_inv_matrix[line_num][col_num],
+                                         matrix_t b_vec[], matrix_t sol_vec[])
+{
+    int i, j;
+
+    memset(sol_vec, 0, col_num * sizeof(matrix_t));
+
+    for (i = 0; i < line_num; i++) {
+        for (j = 0; j < col_num; j++) {
+            sol_vec[i] += pseudo_inv_matrix[i][j] * b_vec[j];
+        }
+    }
+}
diff --git a/localization/position_optimization/doc.txt b/localization/position_optimization/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..89c9383ed82262745072c409c542f412596ff347
--- /dev/null
+++ b/localization/position_optimization/doc.txt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    position_optimization POSITION_OPTIMIZATION
+ * @ingroup     localization
+ * 
+ * @brief       position optimization of distance- and magnetic-based localization systems.
+ *
+ * @details The optimization module enables the refinement of a position of a mobile device 
+ *          using algorithms such as Gauss--Newton, Levenberg, or a Multipath Distance Detection
+ *          and Mitigation (MDDM) algorithm.
+ *
+ * @author      Zakaria Kasmi
+ */
diff --git a/localization/position_optimization/include/loc_gauss_newton.h b/localization/position_optimization/include/loc_gauss_newton.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a88480fa13e1d20fd8539b74a85dfd97e1031c2
--- /dev/null
+++ b/localization/position_optimization/include/loc_gauss_newton.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     position_optimization
+ * @{
+ *
+ * @file
+ * @brief       Implement the Gauss--Newton algorithm for position optimization.
+ * @note        This function is adapted for localization algorithms.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#ifndef LOC_GAUSS_NEWTON_H_
+#define LOC_GAUSS_NEWTON_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+#include "vector.h"
+
+/**
+ * @brief   Implements the modified Gauss--Newton algorithm.
+ * @details The user should provide pointers to the error and Jacobian functions.
+ * @note    This function is optimized for localization algorithms.
+ *
+ * @param[in] ref_points_num           number of the reference stations.
+ * @param[in] ref_points_matrix[][]    three-dimensional coordinates of the reference stations.
+ * @param[in] start_pos[]              start (approximate) position.
+ * @param[in] measured_data_vec[]      pointer to the measured data.
+ * @param[in] eps                      accuracy bound.
+ * @param[in] fmin                     termination tolerance on the error function.
+ * @param[in] max_iter_num             maximal iteration number of the Gauss-Newton algorithm.
+ * @param[in, out] est_pos[]           estimated (optimized) position.
+ * @param[in] (*f_i)                   pointer to the error function.
+ * @param[in] (*jacobian_get_JTJ)      pointer to the function that calculates the
+ *                                     \f$ J_f^{T} J_{f} \f$ matrix.
+ * @param[in] (*jacobian_get_JTf)      pointer to the function that calculates the
+ *                                     \f$ J_f^{T} \vec{f} \f$ vector.
+ *
+ * @return  required iteration number.
+ */
+uint8_t loc_gauss_newton(uint8_t ref_points_num,
+                         matrix_t ref_points_matrix[ref_points_num][3],
+                         vector_t start_pos[3],
+                         matrix_t measured_data_vec[ref_points_num],
+                         matrix_t eps, matrix_t fmin, uint8_t max_iter_num,
+                         vector_t est_pos[3],
+                         void (*f_i)(uint8_t ref_point_num,
+                                     matrix_t ref_point_mat[ref_points_num][3],
+                                     matrix_t point[3], matrix_t d_vec[],
+                                     matrix_t f_vec[]),
+                         void (*jacobian_get_JTJ)(uint8_t ref_points_num,
+                                                  matrix_t ref_point_matrix[ref_points_num][3],
+                                                  matrix_t point[3],
+                                                  matrix_t data_vec[ref_points_num],
+                                                  matrix_t JTJ[3][3]),
+                         void (*jacobian_get_JTf)(uint8_t ref_points_num,
+                                                  matrix_t ref_point_matrix[ref_points_num][3],
+                                                  matrix_t point[3],
+                                                  matrix_t data_vec[ref_points_num],
+                                                  matrix_t JTf[3])
+                         );
+
+#endif /* LOC_GAUSS_NEWTON_H_ */
diff --git a/localization/position_optimization/include/loc_levenberg_marquardt.h b/localization/position_optimization/include/loc_levenberg_marquardt.h
new file mode 100644
index 0000000000000000000000000000000000000000..108832e57983da987779e4777ba9d51f79f66693
--- /dev/null
+++ b/localization/position_optimization/include/loc_levenberg_marquardt.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     position_optimization
+ * @{
+ *
+ * @file
+ * @brief       Implement the Levenberg--Marquardt (LVM) algorithm for position optimization.
+ * @note        This function is adapted for localization algorithms.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef LOC_LEVENBERG_MARQUARDT_H_
+#define LOC_LEVENBERG_MARQUARDT_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Implements the Levenberg--Marquardt (LVM) algorithm.
+ * @details The user should provide pointers to the error and Jacobian functions.
+ * @note    This function is optimized for localization algorithms.
+ *
+ * @param[in] ref_points_num              number of the reference stations.
+ * @param[in] ref_points_matrix[][]       three-dimensional coordinates of the reference stations.
+ * @param[in] start_pos[]                 start (approximate) position.
+ * @param[in] measured_data_vec[]         pointer to the measured data.
+ * @param[in] eps                         accuracy bound.
+ * @param[in] tau                         \f$ \tau \f$ factor.
+ * @param[in] beta0                       \f$ \beta_0 \f$ factor.
+ * @param[in] beta1                       \f$ \beta_1 \f$ factor.
+ * @param[in] max_iter_num                maximal iteration number of the LVM algorithm.
+ * @param[out] est_pos[]                  estimated (optimized) position.
+ * @param[in] (*f_i)                      pointer to the error function.
+ * @param[in] (*jacobian_get_JTJ)         pointer to the function that calculates the matrix
+ *                                        \f$ J_f^{T} J_{f} \f$.
+ * @param[in] (*jacobian_get_JTf)         pointer to the function that calculates the vector
+ *                                        \f$ J_f^{T} \vec{f} \f$.
+ * @param[in] (*jacobian_get_J_mul_s)     pointer to the function that calculates the vector
+ *                                        \f$ J_f^{T} \vec{s} \f$.
+ *
+ * @return  required iteration number.
+ */
+uint8_t loc_levenberg_marquardt(uint8_t ref_points_num,
+                                matrix_t ref_points_matrix[ref_points_num][3],
+                                matrix_t start_pos[3],
+                                matrix_t measured_data_vec[ref_points_num],
+                                matrix_t eps, matrix_t tau, matrix_t beta0,
+                                matrix_t beta1, uint8_t max_iter_num,
+                                matrix_t est_pos[3],
+                                void (*f_i)(uint8_t ref_points_num,
+                                            matrix_t ref_point_mat[ref_points_num][3],
+                                            matrix_t point[3], matrix_t d_vec[], matrix_t f_vec[]),
+                                void (*jacobian_get_JTJ)(uint8_t ref_points_num,
+                                                         matrix_t ref_point_matrix[][3],
+                                                         matrix_t point[3],
+                                                         matrix_t data_vec[ref_points_num],
+                                                         matrix_t JTJ[3][3]),
+                                void (*jacobian_get_JTf)(uint8_t ref_points_num,
+                                                         matrix_t ref_point_matrix[][3],
+                                                         matrix_t point[3],
+                                                         matrix_t data_vec[ref_points_num],
+                                                         matrix_t JTf[3]),
+                                void (*jacobian_get_J_mul_s)(uint8_t ref_points_num,
+                                                             matrix_t ref_point_matrix[][3],
+                                                             matrix_t point[3],
+                                                             matrix_t s[3],
+                                                             matrix_t J_s[ref_points_num])
+                                );
+
+/**
+ * @brief   Implements the correction-function of the Levenberg--Marquardt (LVM) algorithm.
+ * @details The user should provide pointers to the error and Jacobian functions.
+ * @note    This function is optimized for localization algorithms.
+ *
+ * @param[in] ref_points_num           number of the reference stations.
+ * @param[in] ref_points_matrix[][]    three-dimensional coordinates of the reference stations.
+ * @param[in] point[]                  a position to adjust.
+ * @param[in] measured_data_vec[]      pointer to the measured data.
+ * @param[in] mu                       regularization parameter \f$ \mu \f$.
+ * @param[out] s[]                     correction vector.
+ * @param[in] (*f_i)                   pointer to the error function.
+ * @param[in] (*jacobian_get_JTJ)      pointer to the function that calculates the matrix
+ *                                     \f$ J_f^{T} J_{f} \f$.
+ * @param[in] (*jacobian_get_JTf)      pointer to the function that calculates the vector
+ *                                     \f$ J_f^{T} \vec{f} \f$.
+ * @param[in] (*jacobian_get_J_mul_s)  pointer to the function that calculates the vector
+ *                                     \f$ J_f^{T} \vec{s} \f$
+ *
+ *
+ * @return  the parameter \f$ \rho_{\mu} \f$
+ */
+matrix_t loc_levenberg_marquardt_correction(uint8_t ref_points_num,
+                                            matrix_t ref_points_matrix[ref_points_num][3],
+                                            matrix_t point[3],
+                                            matrix_t measured_data_vec[ref_points_num],
+                                            matrix_t mu, matrix_t s[3],
+                                            void (*f_i)(uint8_t ref_point_num,
+                                                        matrix_t ref_point_mat[ref_points_num][3],
+                                                        matrix_t point[3],
+                                                        matrix_t d_vec[], matrix_t f_vec[]),
+                                            void (*jacobian_get_JTJ)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3],
+                                                matrix_t data_vec[ref_points_num],
+                                                matrix_t JTJ[3][3]),
+                                            void (*jacobian_get_JTf)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3],
+                                                matrix_t data_vec[ref_points_num],
+                                                matrix_t JTf[3]),
+                                            void (*jacobian_get_J_mul_s)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3], matrix_t s[3],
+                                                matrix_t J_s[ref_points_num])
+                                            );
+/**
+ * @brief   Compute the initial value \f$ \mu_0 \f$ of the Levenberg--Marquardt (LVM) algorithm.
+ * @details The user should provide a pointer to the matrix
+ *          \f$ J_f^{T} J_{f} \f$.
+ *
+ *
+ * @param[in] tau        \f$ \tau \f$ factor.
+ * @param[in] JTJ[][]    pointer to the matrix \f$ J_f^T J_f \f$.
+ *
+ * @return   \f$ \rho_{\mu} \f$-parameter
+ */
+matrix_t loc_levenberg_marquardt_get_mu0(matrix_t tau, matrix_t JTJ[3][3]);
+
+//compute: J'J + mu^2*I
+
+/**
+ * @brief   Compute the matrix
+ *          \f$ J_f^{T} J_f + \mu^{(i)})^{2} I \f$.
+ * @note    This function is optimized for localization algorithms.
+ *
+ * @param[in] ref_points_num           number of the reference stations.
+ * @param[in] ref_points_matrix[][]    three-dimensional coordinates of the reference stations.
+ * @param[in] point[]                  a position to adjust.
+ * @param[in] measured_data_vec[]      pointer to the measured data.
+ * @param[in] mu                       \f$ \rho_{\mu} \f$-parameter
+ * @param[out] JTJ_mu2_I[][]           includes the matrix
+ *                                     \f$ J_f^{T} J_f + \mu^{(i)})^{2} I \f$.
+ * @param[in] (*jacobian_get_JTJ)      pointer to the function that calculates the matrix
+ *                                     \f$ J_f^{T} J_{f} \f$.
+ *
+ */
+void loc_levenberg_marquardt_get_JTJ_mu2_I(uint8_t ref_points_num,
+                                           matrix_t ref_points_matrix[ref_points_num][3],
+                                           matrix_t point[3],
+                                           matrix_t measured_data_vec[ref_points_num], matrix_t mu,
+                                           matrix_t JTJ_mu2_I[3][3],
+                                           void (*jacobian_get_JTJ)(
+                                               uint8_t ref_points_num,
+                                               matrix_t ref_point_matrix[ref_points_num][3],
+                                               matrix_t point[3],
+                                               matrix_t data_vec[ref_points_num],
+                                               matrix_t JTJ[3][3])
+                                           );
+
+#endif /* LOC_LEVENBERG_MARQUARDT_H_*/
diff --git a/localization/position_optimization/include/multipath_dist_detection_mitigation.h b/localization/position_optimization/include/multipath_dist_detection_mitigation.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e7089da3a6220bf756ccdc04c9590b2e28932a5
--- /dev/null
+++ b/localization/position_optimization/include/multipath_dist_detection_mitigation.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     position_optimization
+ * @{
+ *
+ * @file
+ * @brief       Implement the Multipath Distance Detection and Mitigation (MDDM) algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef POSITIONING_ROBUST_OTF_H_
+#define POSITIONING_ROBUST_OTF_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+
+/**
+ * @brief   Computes the exact distance between a mobile station and a reference station.
+ *
+ *
+ * @param[in] ref_point    three-dimensional coordinates of a reference station.
+ * @param[in] exact_point  three-dimensional coordinates of the mobile device.
+ *
+ * @return    the exact distance between the mobile station and the reference station.
+ */
+matrix_t get_exact_distance_to_anchor(matrix_t ref_point[],
+                                      uint32_t exact_point[]);
+/**
+ * @brief   Determine if a candidate is a multipath or not.
+ *
+ * @param[in] vector          a candidate.
+ * @param[in] n               size of the multipath-vector.
+ * @param[in] multipath[]     pointer to the multipath-vector.
+ *
+ * @return true, if a candidate is a multipath.
+ * @return false, if not.
+ *
+ */
+bool is_member(matrix_t vector, uint8_t n, matrix_t multipath[n]);
+
+/**
+ * @brief   Determine if a point is an anchor or not.
+ *
+ * @param[in] m               number of the reference points.
+ * @param[in] ref_matr[][]    three-dimensional coordinates of the reference stations.
+ * @param[in] point[]         three-dimensional coordinates of a point.
+ *
+ * @return true, if a point is an anchor.
+ * @return false, if not.
+ */
+bool is_anchor(uint8_t m, matrix_t ref_matr[m][3], uint32_t point[3]);
+
+/**
+ * @brief    Simulate an UWB-based localization system.
+ * @details  The UWB system is simulated by noising the distances from a mobile to the reference
+ *           station.
+ *
+ * @param[in] m               number of the reference points.
+ * @param[in] ref_matrix[][]  three-dimensional coordinates of the reference stations.
+ * @param[in] exact_point[]   three-dimensional coordinates of a true position.
+ * @param[in] sigma           \f$ \sigma_{M,W} \f$ parameter.
+ * @param[in] n               number of the multipath-affected distances.
+ * @param[in] multipath[]     multipath vector.
+ * @param[in] seed            seed value.
+ * @param[in] r_noised_vec[]  noised distances.
+ *
+ */
+void sim_UWB_dist(uint8_t m, matrix_t ref_matrix[m][3], uint32_t exact_point[],
+                  matrix_t sigma, uint8_t n, matrix_t multipath[n], int seed,
+                  matrix_t r_noised_vec[]);
+/**
+ * @brief    Compute the optimal partial matrix including reference points.
+ *
+ * @param[in] anchors_num                  number of the reference points.
+ * @param[in] ref_matrix[][]               three-dimensional coordinates of the reference stations.
+ * @param[in] k                            k anchors (possible sub-experiments).
+ * @param[in] optimal_anchors_comb[]       optimal anchor combination.
+ * @param[out] opt_partial_ref_matrix[][]  optimal partial matrix of anchors.
+ *
+ */
+void get_optimal_partial_ref_matrix(uint8_t anchors_num,
+                                    matrix_t ref_matrix[anchors_num][3],
+                                    uint8_t k, uint8_t optimal_anchors_comb[k],
+                                    matrix_t opt_partial_ref_matrix[k][3]);
+
+/**
+ * @brief    Compute noised distances corresponding to the optimal partial matrix.
+ *
+ * @param[in] k                                 k anchors (possible sub-experiments).
+ * @param[in] r_noised_vec[]                    include noised distances.
+ * @param[in] optimal_anchors_comb[]            optimal k-anchor combination.
+ * @param[in, out] opt_sub_r_noised_vec[][]     noised distances corresponding to the optimal
+ *                                              k-anchors.
+ *
+ */
+void get_optimal_partial_r_noised_vec(uint8_t k, matrix_t r_noised_vec[],
+                                      uint8_t optimal_anchors_comb[k],
+                                      matrix_t opt_sub_r_noised_vec[k]);
+
+/**
+ * @brief   Implement the Multipath Distance Detection and Mitigation (MDDM) algorithm.
+ *
+ * @param[in] k                         k anchors (possible sub-experiments).
+ * @param[in] m                         number of anchors.
+ * @param[in] ref_Matrix[][]            three-dimensional coordinates of the reference stations.
+ * @param[in] r_noised_vec[]            include noised distances.
+ * @param[in] anchors_optimal[]         optimal k-anchor combination.
+ * @param[in, out] start_optimal[]      optimal position.
+ *
+ */
+void recog_mitigate_multipath(uint8_t k, uint8_t m, matrix_t ref_Matrix[m][3],
+                              matrix_t r_noised_vec[m],
+                              uint8_t anchors_optimal[k],
+                              matrix_t start_optimal[3]);
+
+#endif /* POSITIONING_ROBUST_OTF_H_ */
diff --git a/localization/position_optimization/loc_gauss_newton.c b/localization/position_optimization/loc_gauss_newton.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c352a313b4dd6b9a819a7e1198a2d4782c5e2f8
--- /dev/null
+++ b/localization/position_optimization/loc_gauss_newton.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Gauss--Newton algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#include <stdio.h>
+
+#include "utils.h"
+#include "matrix.h"
+#include "vector.h"
+#include "moore_penrose_pseudo_inverse.h"
+
+uint8_t loc_gauss_newton(uint8_t ref_points_num,
+                         matrix_t ref_points_matrix[ref_points_num][3],
+                         vector_t start_pos[3],
+                         matrix_t measured_data_vec[ref_points_num],
+                         matrix_t eps, matrix_t fmin, uint8_t max_iter_num,
+                         vector_t est_pos[3],
+                         void (*f_i)(uint8_t ref_point_num,
+                                     matrix_t ref_point_mat[ref_points_num][3],
+                                     matrix_t point[3], matrix_t d_vec[],
+                                     matrix_t f_vec[]),
+                         void (*jacobian_get_JTJ)(uint8_t ref_points_num,
+                                                  matrix_t ref_point_matrix[ref_points_num][3],
+                                                  matrix_t point[3],
+                                                  matrix_t data_vec[ref_points_num],
+                                                  matrix_t JTJ[3][3]),
+                         void (*jacobian_get_JTf)(uint8_t ref_points_num,
+                                                  matrix_t ref_point_matrix[ref_points_num][3],
+                                                  matrix_t point[3],
+                                                  matrix_t data_vec[ref_points_num],
+                                                  matrix_t JTf[3])
+                         )
+{
+
+    matrix_t JT_J[3][3];
+    matrix_t JT_f[3];
+    matrix_t f_vec[ref_points_num];
+    matrix_t f_error;
+    matrix_t pinv_JTJ_mat[3][3];
+    matrix_t correction_vec[3];
+    matrix_t pos[3];
+    matrix_t next_pos[3];
+    matrix_t max_error, min_error;
+    matrix_t step;
+    uint8_t iter_num;
+
+    f_i(ref_points_num, ref_points_matrix, start_pos, measured_data_vec,
+        f_vec);
+    f_error = vector_get_norm2(ref_points_num, f_vec);
+    max_error = f_error;
+    min_error = max_error;
+    step = eps;
+
+    vector_copy(3, start_pos, pos);
+    vector_copy(3, start_pos, est_pos);
+    iter_num = 0;
+    while ((step >= eps) && (iter_num < max_iter_num) && (f_error > fmin)) {
+        /*
+         * Compute then correction terms & next positions
+         */
+
+        //JTJ
+        jacobian_get_JTJ(ref_points_num, ref_points_matrix, pos,
+                         measured_data_vec, JT_J);
+
+        //JTf
+        jacobian_get_JTf(ref_points_num, ref_points_matrix, pos,
+                         measured_data_vec, JT_f);
+
+        //solve: J'J*s = -J'*f
+        moore_penrose_get_pinv(3, 3, JT_J, pinv_JTJ_mat);
+        //s = (J'J)\J'*f
+        matrix_mul_vec(3, 3, pinv_JTJ_mat, JT_f, correction_vec);
+
+        // x = x - s
+        vector_sub(3, pos, correction_vec, next_pos);
+
+        //next step
+        step = vector_get_euclidean_distance(3, pos, next_pos);
+
+        // pos = next_pos
+        vector_copy(3, next_pos, pos);
+
+        //error vector
+        f_i(ref_points_num, ref_points_matrix, pos, measured_data_vec,
+            f_vec);
+        f_error = vector_get_norm2(ref_points_num, f_vec);
+
+        if (min_error > f_error) {  //store the position with the minimum error
+            vector_copy(3, pos, est_pos);
+            min_error = f_error;    // update min_error
+        }
+
+        max_error = utils_max(f_error, max_error); // update max_error
+        iter_num++;
+        if ((max_error - min_error) > 10) {
+            break;
+        }
+
+    } //while
+
+    return iter_num;
+}
diff --git a/localization/position_optimization/loc_levenberg_marquardt.c b/localization/position_optimization/loc_levenberg_marquardt.c
new file mode 100644
index 0000000000000000000000000000000000000000..36d5b2b187c728d78c23fd6e0149afcf182ec7f6
--- /dev/null
+++ b/localization/position_optimization/loc_levenberg_marquardt.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Levenberg--Marquardt (LVM) algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+#include <inttypes.h>
+
+#include "matrix.h"
+#include "vector.h"
+#include "solve.h"
+#include "utils.h"
+#include "loc_levenberg_marquardt.h"
+
+matrix_t loc_levenberg_marquardt_correction(uint8_t ref_points_num,
+                                            matrix_t ref_points_matrix[ref_points_num][3],
+                                            matrix_t point[3],
+                                            matrix_t measured_data_vec[ref_points_num], matrix_t mu,
+                                            matrix_t s[3],
+                                            void (*f_i)(uint8_t ref_point_num,
+                                                        matrix_t ref_point_mat[ref_points_num][3],
+                                                        matrix_t point[3], matrix_t d_vec[],
+                                                        matrix_t f_vec[]),
+                                            void (*jacobian_get_JTJ)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3],
+                                                matrix_t data_vec[ref_points_num],
+                                                matrix_t JTJ[3][3]),
+                                            void (*jacobian_get_JTf)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3],
+                                                matrix_t data_vec[ref_points_num],
+                                                matrix_t JTf[3]),
+                                            void (*jacobian_get_J_mul_s)(
+                                                uint8_t ref_points_num,
+                                                matrix_t ref_point_matrix[ref_points_num][3],
+                                                matrix_t point[3], matrix_t s[3],
+                                                matrix_t J_s[ref_points_num])
+                                            )
+{
+
+    matrix_t Fx[ref_points_num];
+    matrix_t JTJ_mu2_I[3][3];
+    matrix_t JTF[3];
+    matrix_t ro_mu = 0;
+    matrix_t Fx_square = 0;
+    matrix_t Fx_plus_s_square = 0;
+    matrix_t Fx_plus_J_mul_s_square = 0;
+    matrix_t Fx_plus_J_mul_s[ref_points_num];
+    matrix_t F_x_plus_s[ref_points_num];
+    matrix_t point_plus_s[3];
+    matrix_t denom;
+
+    //compute: -(J'J + mu^2*I)
+    loc_levenberg_marquardt_get_JTJ_mu2_I(ref_points_num, ref_points_matrix,
+                                          point,
+                                          measured_data_vec, mu, JTJ_mu2_I,
+                                          jacobian_get_JTJ);
+    matrix_mul_scalar(3, 3, JTJ_mu2_I, -1, JTJ_mu2_I); // -(J'*J+mu^2*eye(n)) is an (n,n) matrix
+
+    jacobian_get_JTf(ref_points_num, ref_points_matrix, point,
+                     measured_data_vec, JTF);
+
+    //solve the equation: s = -(J'*J+mu^2*I)\(J'*Fx);
+    solve_householder(3, 3, JTJ_mu2_I, JTF, s);
+
+    //f(x)
+    f_i(ref_points_num, ref_points_matrix, point, measured_data_vec, Fx);
+    //f(x)^2
+    Fx_square = vector_get_scalar_product(ref_points_num, Fx, Fx);
+
+    //(x+s)
+    vector_add(3, point, s, point_plus_s);
+
+    //f(x+s)
+    f_i(ref_points_num, ref_points_matrix, point_plus_s, measured_data_vec,
+        F_x_plus_s);
+    //f(x+s)^2
+    Fx_plus_s_square = vector_get_scalar_product(ref_points_num, F_x_plus_s,
+                                                 F_x_plus_s);
+
+    //compute: J(x)*s
+    jacobian_get_J_mul_s(ref_points_num, ref_points_matrix, point, s,
+                         Fx_plus_J_mul_s);
+    //compute: f(x) + J(x)*s
+    vector_add(ref_points_num, Fx, Fx_plus_J_mul_s, Fx_plus_J_mul_s);
+
+    //compute: ||f(x) + J(x)*s||^2
+    Fx_plus_J_mul_s_square = vector_get_scalar_product(ref_points_num,
+                                                       Fx_plus_J_mul_s,
+                                                       Fx_plus_J_mul_s);
+
+    denom = Fx_square - Fx_plus_J_mul_s_square;
+    if (denom != 0) {
+        ro_mu = (Fx_square - Fx_plus_s_square) / denom;
+    }
+    else {
+        puts("ro_mu is infinite !!!");
+        ro_mu = FLT_MAX;
+    }
+
+    return ro_mu;
+}
+
+uint8_t loc_levenberg_marquardt(uint8_t ref_points_num,
+                                matrix_t ref_points_matrix[ref_points_num][3],
+                                matrix_t start_pos[3],
+                                matrix_t measured_data_vec[ref_points_num],
+                                matrix_t eps, matrix_t tau, matrix_t beta0,
+                                matrix_t beta1,
+                                uint8_t max_iter_num,
+                                matrix_t est_pos[3],
+                                void (*f_i)(uint8_t ref_points_num,
+                                            matrix_t ref_point_mat[ref_points_num][3],
+                                            matrix_t point[3], matrix_t d_vec[],
+                                            matrix_t f_vec[]),
+                                void (*jacobian_get_JTJ)(uint8_t ref_points_num,
+                                                         matrix_t ref_point_matrix[][3],
+                                                         matrix_t point[3],
+                                                         matrix_t data_vec[ref_points_num],
+                                                         matrix_t JTJ[3][3]),
+                                void (*jacobian_get_JTf)(uint8_t ref_points_num,
+                                                         matrix_t ref_point_matrix[][3],
+                                                         matrix_t point[3],
+                                                         matrix_t data_vec[ref_points_num],
+                                                         matrix_t JTf[3]),
+                                void (*jacobian_get_J_mul_s)(uint8_t ref_points_num,
+                                                             matrix_t ref_point_matrix[][3],
+                                                             matrix_t point[3], matrix_t s[3],
+                                                             matrix_t J_s[ref_points_num])
+                                )
+{
+
+    matrix_t JTF[3];
+    matrix_t JTJ_mu2_I[3][3];
+    matrix_t s[3];
+    matrix_t mu;
+    matrix_t ro_mu;
+    uint8_t it;
+
+    /*
+     * compute mu0 and -(J'J + mu0^2*I)
+     */
+    //store J'J in JTJ_mu2_I
+    jacobian_get_JTJ(ref_points_num, ref_points_matrix, start_pos,
+                     measured_data_vec, JTJ_mu2_I);
+    mu = loc_levenberg_marquardt_get_mu0(tau, JTJ_mu2_I);
+
+    //compute: J'J + mu0^2*I
+    loc_levenberg_marquardt_get_JTJ_mu2_I(ref_points_num, ref_points_matrix,
+                                          start_pos, measured_data_vec, mu,
+                                          JTJ_mu2_I,
+                                          jacobian_get_JTJ);
+    //-(J'*J+mu0^2*eye(n)) is an (n,n) matrix
+    matrix_mul_scalar(3, 3, JTJ_mu2_I, -1, JTJ_mu2_I);
+
+    //compute JTF
+    jacobian_get_JTf(ref_points_num, ref_points_matrix, start_pos,
+                     measured_data_vec, JTF);
+
+    //solve the equation: s=-(J'*J+mu^2*eye(n))\(J'*F);
+    solve_householder(3, 3, JTJ_mu2_I, JTF, s);
+
+    vector_copy(3, start_pos, est_pos);
+    it = 0;
+    while ((vector_get_norm2(3, s)
+            > eps * (1 + vector_get_norm2(3, est_pos)))
+           && (it < max_iter_num)) {   //norm(s,2)>eps*(1+norm(x,2))
+
+        ro_mu = loc_levenberg_marquardt_correction(ref_points_num,
+                                                   ref_points_matrix, est_pos,
+                                                   measured_data_vec,
+                                                   mu, s, f_i, jacobian_get_JTJ,
+                                                   jacobian_get_JTf,
+                                                   jacobian_get_J_mul_s);
+
+        while (1) {
+            if (ro_mu <= beta0) {
+                mu = 2.0 * mu;
+                ro_mu = loc_levenberg_marquardt_correction(
+                    ref_points_num,
+                    ref_points_matrix, est_pos,
+                    measured_data_vec, mu, s, f_i,
+                    jacobian_get_JTJ,
+                    jacobian_get_JTf,
+                    jacobian_get_J_mul_s);
+            }
+            else if (ro_mu >= beta1) {
+                mu = mu / 2.0;
+                break;
+            }
+            else {
+                break;
+            }
+        }
+        vector_add(3, est_pos, s, est_pos);
+        it = it + 1;
+    } //while
+    return it;
+}
+
+matrix_t loc_levenberg_marquardt_get_mu0(matrix_t tau, matrix_t JTJ[3][3])
+{
+    matrix_t max_diag_JTJ = JTJ[0][0];
+
+    for (uint8_t i = 1; i < 3; i++) {
+        if (JTJ[i][i] > max_diag_JTJ) {
+            max_diag_JTJ = JTJ[i][i];
+        }
+    }
+    return tau * max_diag_JTJ;
+}
+
+//compute: J'J + mu^2*I
+void loc_levenberg_marquardt_get_JTJ_mu2_I(uint8_t ref_points_num,
+                                           matrix_t ref_points_matrix[ref_points_num][3],
+                                           matrix_t point[3],
+                                           matrix_t measured_data_vec[ref_points_num],
+                                           matrix_t mu,
+                                           matrix_t JTJ_mu2_I[3][3],
+                                           void (*jacobian_get_JTJ)(
+                                               uint8_t ref_points_num,
+                                               matrix_t ref_point_matrix[ref_points_num][3],
+                                               matrix_t point[3],
+                                               matrix_t data_vec[ref_points_num],
+                                               matrix_t JTJ[3][3])
+                                           )
+{
+    uint8_t i;
+
+    jacobian_get_JTJ(ref_points_num, ref_points_matrix, point,
+                     measured_data_vec, JTJ_mu2_I); //JTJ_mu2_I = J'J
+
+    for (i = 0; i < 3; i++) {
+        JTJ_mu2_I[i][i] += pow(mu, 2);  // JTJ_mu2_I = J'*J+mu^2*I;
+    }
+}
diff --git a/localization/position_optimization/multipath_dist_detection_mitigation.c b/localization/position_optimization/multipath_dist_detection_mitigation.c
new file mode 100644
index 0000000000000000000000000000000000000000..b88c692a43786556419c295fc79bbea104de7739
--- /dev/null
+++ b/localization/position_optimization/multipath_dist_detection_mitigation.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Multipath Distance Detection and Mitigation (MDDM) algorithm.
+ *
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <float.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "matrix.h"
+#include "vector.h"
+#include "combinatorics.h"
+#include "multipath_dist_detection_mitigation.h"
+#include "norm_dist_rnd_generator.h"
+#include "shell_sort.h"
+#include "dist_based_position.h"
+#include "DOP.h"
+#include "trilateration.h"
+
+matrix_t get_exact_distance_to_anchor(matrix_t ref_point[],
+                                      uint32_t exact_point[])
+{
+    matrix_t d = sqrt(
+        pow((exact_point[0] - ref_point[0]), 2)
+        + pow((exact_point[1] - ref_point[1]),
+              2)
+        + pow((exact_point[2] - ref_point[2]),
+              2));
+
+    return d;
+}
+
+bool is_member(matrix_t vector, uint8_t n, matrix_t multipath[n])
+{
+    for (int i = 0; i < n; i++) {
+        if (vector == multipath[i]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool is_anchor(uint8_t m, matrix_t ref_matr[m][3], uint32_t point[3])
+{
+
+    for (uint8_t i = 0; i < m; i++) {
+        if (point[0] == ref_matr[i][0] && point[1] == ref_matr[i][1]
+            && point[2] == ref_matr[i][2]) {
+            return true;
+        }
+
+    }
+    return false;
+}
+
+void sim_UWB_dist(uint8_t m, matrix_t ref_matrix[m][3], uint32_t exact_point[],
+                  matrix_t sigma, uint8_t n, matrix_t multipath[n], int seed,
+                  matrix_t r_noised_vec[])
+{
+    matrix_t M_UW = 0.88;
+    matrix_t sigma_UW = 1.522;
+    matrix_t R = 0.0;
+
+    // set seed
+    get_rand_num(seed);
+
+    for (int i = 0; i < m; i++) {
+        matrix_t d = get_exact_distance_to_anchor(ref_matrix[i],
+                                                  exact_point);
+
+        if (is_member(i + 1, n, multipath) == true) {
+
+            R = log(1 + d)
+                * get_norm_distr_rand_num(M_UW,
+                                          sigma_UW);
+
+        }
+        else {
+
+            R = sigma * get_norm_distr_rand_num(0, 1);
+        }
+        r_noised_vec[i] = R + d;
+    }
+}
+
+void get_optimal_partial_ref_matrix(uint8_t anchors_num,
+                                    matrix_t ref_matrix[anchors_num][3],
+                                    uint8_t k,
+                                    uint8_t optimal_anchors_comb[k],
+                                    matrix_t opt_partial_ref_matrix[k][3])
+{
+    for (int i = 0; i < k; i++) {
+        for (int j = 0; j < 3; j++) {
+            opt_partial_ref_matrix[i][j] =
+                ref_matrix[optimal_anchors_comb[i]][j];
+
+        }
+    }
+}
+
+void get_optimal_partial_r_noised_vec(uint8_t k, matrix_t r_noised_vec[],
+                                      uint8_t optimal_anchors_comb[k],
+                                      matrix_t opt_sub_r_noised_vec[k])
+{
+    for (int i = 0; i < k; i++) {
+        opt_sub_r_noised_vec[i] = r_noised_vec[optimal_anchors_comb[i]];
+
+    }
+}
+
+void recog_mitigate_multipath(uint8_t k, uint8_t m, matrix_t ref_matrix[m][3],
+                              matrix_t noised_r_vec[m],
+                              uint8_t anchors_optimal_combi[k],
+                              matrix_t start_optimal_pos[3])
+{
+    int8_t status_num;
+    uint8_t combi_arr[k];
+    matrix_t r_vec[3];
+    matrix_t part_opt_ref_matrix[k][3];
+    matrix_t opt_part_r_noised_vec[k];
+    uint8_t index_vector[k];
+    matrix_t qres_optimal = FLT_MAX;
+    matrix_t pos_solution_x1[4];
+
+    // Initialize the combination generator
+    status_num = combinatorics_init(m, k, combi_arr);
+
+    if (status_num == COMBI_ERROR) {
+        fprintf(stderr,
+                "Error: couldn't initialize the combination generator\n");
+
+        return;
+    }
+
+    while (status_num == COMBI_SUCCESS) {
+        get_optimal_partial_ref_matrix(m, ref_matrix, k, combi_arr,
+                                       part_opt_ref_matrix);
+
+        get_optimal_partial_r_noised_vec(k, noised_r_vec, combi_arr,
+                                         opt_part_r_noised_vec);
+        // Trilateration
+        trilateration2(k, part_opt_ref_matrix, opt_part_r_noised_vec,
+                       pos_solution_x1,
+                       NULL);
+
+        matrix_t residual_vec[m];
+        matrix_t residual_vec_copy[m];
+
+        for (int i = 0; i < m; i++) {
+
+            vector_sub(3, pos_solution_x1 + 1, ref_matrix[i],
+                       r_vec);
+            residual_vec[i] = vector_get_norm2(3, r_vec)
+                              - noised_r_vec[i];
+        }
+
+        vector_square(m, residual_vec, residual_vec);
+
+        vector_copy(m, residual_vec, residual_vec_copy);
+
+        shell_sort(residual_vec_copy, m);
+
+        // find index
+        vector_get_index_vector(k, m, residual_vec, residual_vec_copy,
+                                index_vector);
+
+        matrix_t res_vec_copy_sum = 0;
+
+        for (int i = 0; i < k; i++) {
+            res_vec_copy_sum = res_vec_copy_sum
+                               + residual_vec_copy[i];
+        }
+
+        if (res_vec_copy_sum <= qres_optimal) {
+            qres_optimal = res_vec_copy_sum;
+            memcpy(anchors_optimal_combi, index_vector,
+                   k * sizeof(uint8_t));
+            vector_copy(3, pos_solution_x1 + 1, start_optimal_pos);
+        }
+        status_num = combinatorics_get_next_without_rep(m, k,
+                                                        combi_arr);
+    } //while
+}