From b7f35fa4017a55655eb8780b28991607f6c2084b Mon Sep 17 00:00:00 2001
From: joanvallve <jvallve@iri.upc.edu>
Date: Fri, 19 Mar 2021 17:11:32 +0100
Subject: [PATCH] working!

---
 include/gnss_utils/tdcp.h |   4 +-
 src/tdcp.cpp              |  37 ++++++++++----
 test/gtest_tdcp.cpp       | 105 +++++++++++++++++++++++++++++++-------
 3 files changed, 117 insertions(+), 29 deletions(-)

diff --git a/include/gnss_utils/tdcp.h b/include/gnss_utils/tdcp.h
index 5cc3919..deb5aed 100644
--- a/include/gnss_utils/tdcp.h
+++ b/include/gnss_utils/tdcp.h
@@ -46,7 +46,7 @@ bool Tdcp(SnapshotPtr               snapshot_r,
           Eigen::Vector4d&          d,
           Eigen::Matrix4d&          cov_d,
           double&                   residual,
-          std::set<int>             raim_discarded_sats,
+          std::set<int>&            raim_discarded_sats,
           const TdcpBatchParams&    tdcp_params);
 
 bool Tdcp(const Eigen::Vector3d&    x_r,
@@ -58,7 +58,7 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
           Eigen::Vector4d&          d,
           Eigen::Matrix4d&          cov_d,
           double&                   residual,
-          std::set<int>             raim_discarded_sats,
+          std::set<int>&            raim_discarded_sats,
           const TdcpBatchParams&    tdcp_params);
 
 }  // namespace GnssUtils
diff --git a/src/tdcp.cpp b/src/tdcp.cpp
index bb36f5b..8e0b0e0 100644
--- a/src/tdcp.cpp
+++ b/src/tdcp.cpp
@@ -95,7 +95,7 @@ bool Tdcp(SnapshotPtr               snapshot_r,
           Eigen::Vector4d&          d,
           Eigen::Matrix4d&          cov_d,
           double&                   residual,
-          std::set<int>             raim_discarded_sats,
+          std::set<int>&            raim_discarded_sats,
           const TdcpBatchParams&    tdcp_params)
 {
     // CHECKS
@@ -137,7 +137,6 @@ bool Tdcp(SnapshotPtr               snapshot_r,
     double tk = snapshot_k->getGPST();
 
     // MULTI-FREQUENCY
-    // TODO: change obs -> ranges
     std::map<int, std::pair<int, int>> row_2_sat_freq;
     int                                row = 0;
     for (auto sat : common_sats)
@@ -197,7 +196,7 @@ bool Tdcp(SnapshotPtr               snapshot_r,
             drho_m(row) = range_k.L2_corrected - range_r.L2_corrected;
 
         #if GNSS_UTILS_TDCP_DEBUG == 1
-             std::cout << "\tsat " << sat_number
+             std::cout << "\tsat " << sat_number;
              std::cout << std::setprecision(10)
                        << "\tpositions:" << std::endl
                        << "\t\ts_r: " << s_r.col(row).transpose() << std::endl
@@ -244,7 +243,7 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
           Eigen::Vector4d&          d,
           Eigen::Matrix4d&          cov_d,
           double&                   residual,
-          std::set<int>             raim_discarded_rows,
+          std::set<int>&            raim_discarded_rows,
           const TdcpBatchParams&    tdcp_params)
 {
 
@@ -256,6 +255,10 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
         // fill A and r
         for (int row = 0; row < A.rows(); row++)
         {
+            // skip discarded rows
+            if (raim_discarded_rows.count(row) != 0)
+                continue;
+
             // Evaluate r
             r(row) = drho_m(row) - (s_k.col(row) - x_r - d.head(3)).norm() + (s_r.col(row) - x_r).norm() - d(3);
 
@@ -282,6 +285,19 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
         if (d.array().isNaN().any())
         {
             std::cout << "Tdcp: NLS DID NOT WORK. NAN values appeared. ABORTING!!" << std::endl;
+            #if GNSS_UTILS_TDCP_DEBUG == 1
+                std::cout << "Displacement vector =" << d.head<3>().transpose() << std::endl;
+                std::cout << "Displacement update =" << delta_d.head<3>().transpose() << std::endl;
+                printf("Ref distance      = %7.3f m\n", d_0.norm());
+                printf("Computed distance = %7.3f m\n", d.head<3>().norm());
+                printf("Tdcp: rows          = %lu\n", r.rows());
+                std::cout << "Tdcp: r             = " << r.transpose() << std::endl;
+                std::cout << "Tdcp: drho_m        = " << drho_m.transpose() << std::endl;
+                std::cout << "Tdcp: A             = \n" << A << std::endl;
+                std::cout << "Tdcp: H             = \n" << A.transpose() * A << std::endl;
+                std::cout << "Tdcp: cov_d         = \n" << cov_d << std::endl;
+                printf("Tdcp: dT            = %8.3f secs\n", d(3));
+            #endif
             return false;
         }
 
@@ -297,7 +313,7 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
             printf("Ref distance      = %7.3f m\n", d_0.norm());
             printf("Computed distance = %7.3f m\n", d.head<3>().norm());
             printf("Tdcp: residual      = %13.10f\n", residual);
-            printf("Tdcp: row           = %lu\n", r.rows());
+            printf("Tdcp: rows          = %lu\n", r.rows());
             std::cout << "Tdcp: r             = " << r.transpose() << std::endl;
             std::cout << "Tdcp: drho_m        = " << drho_m.transpose() << std::endl;
             std::cout << "Tdcp: A             = \n" << A << std::endl;
@@ -342,16 +358,15 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
                         // residual = sqrt((r_raim + A_raim * delta_d_raim).squaredNorm() / A_raim.rows());
 
                         #if GNSS_UTILS_TDCP_DEBUG == 1
-                            std::cout << "RAIM excluding row " << << row_removed << std::endl;
+                            std::cout << "RAIM excluding row " << row_removed << std::endl;
                             std::cout << "Displacement vector =" << d_raim.head<3>().transpose() << std::endl;
                             std::cout << "Displacement update =" << delta_d_raim.head<3>().transpose() << std::endl;
                             printf("Ref distance      = %7.3f m\n", d_0.norm());
                             printf("Computed distance = %7.3f m\n", d_raim.head<3>().norm());
                             printf("Tdcp: residual      = %13.10f\n", residual);
                             std::cout << "Tdcp: drho          = " << r_raim.transpose() << std::endl;
-                            std::cout << "Tdcp: A             = \n" << A << std::endl;
-                            std::cout << "Tdcp: H             = \n" << A.transpose() * A << std::endl;
-                            std::cout << "Tdcp: cov_d         = \n" << cov_d << std::endl;
+                            std::cout << "Tdcp: A             = \n" << A_raim << std::endl;
+                            std::cout << "Tdcp: H             = \n" << A_raim.transpose() * A_raim << std::endl;
                             printf("Tdcp: dT            = %8.3f secs\n", d_raim(3));
                         #endif
 
@@ -378,6 +393,10 @@ bool Tdcp(const Eigen::Vector3d&    x_r,
                 // store removed sat
                 raim_discarded_rows.insert(worst_sat_row);
 
+                // remove row
+                A.row(worst_sat_row) = Eigen::Vector4d::Zero().transpose();
+                r(worst_sat_row)     = 0;  // not necessary
+
                 /*// Remove selected satellite from problem
                 std::cout << "resizing problem..." << std::endl;
                 auto A_aux      = A;
diff --git a/test/gtest_tdcp.cpp b/test/gtest_tdcp.cpp
index 0b160f3..989c47e 100644
--- a/test/gtest_tdcp.cpp
+++ b/test/gtest_tdcp.cpp
@@ -22,7 +22,7 @@ void computeRandomVisibleSatellite(const Vector3d& receiver_latlonalt,
                                    Vector3d& sat_ENU,
                                    Vector3d& sat_ECEF,
                                    Vector2d& sat_azel,
-                                   double range)
+                                   double& range)
 {
     Vector3d t_ECEF_ENU, t_ENU_ECEF;
     Matrix3d R_ENU_ECEF;
@@ -44,13 +44,23 @@ void computeRandomVisibleSatellite(const Vector3d& receiver_latlonalt,
 
     // ECEF
     sat_ECEF = t_ECEF_ENU + R_ENU_ECEF.transpose() * sat_ENU;
+
+    // Range
+    range = (sat_ECEF - t_ECEF_ENU).norm();
 }
 
 
 TEST(Tdcp, Tdcp)
 {
+    int N_sats = 20;
+
     TdcpBatchParams tdcp_params;
-    // TODO: fill params
+    tdcp_params.max_iterations = 10;
+    tdcp_params.min_common_sats = 6;
+    tdcp_params.raim_n = 2;
+    tdcp_params.raim_min_residual = 0;
+    tdcp_params.relinearize_jacobian = true;
+    tdcp_params.tdcp.multi_freq = false;
 
     Vector3d sat_ENU, sat_ECEF;
     Vector3d x_r_LLA, x_r_ECEF, x_k_LLA, x_k_ECEF, d_ECEF;
@@ -58,58 +68,112 @@ TEST(Tdcp, Tdcp)
     Vector2d azel, azel2;
     Vector4d d, d_gt;
     Matrix4d cov_d;
-    double residual;
-    double range;
-
-    Satellite sat_def({0,0,Vector3d::Zero(),Vector3d::Zero(),1.0,0,0,1});
+    double range, residual;
 
+    // Snapshots
     auto snapshot_r = std::make_shared<Snapshot>();
     auto snapshot_k = std::make_shared<Snapshot>();
 
+    // Observations (just needed for the GPST)
+    snapshot_r->setObservations(std::make_shared<Observations>());
+    snapshot_k->setObservations(std::make_shared<Observations>());
+    obsd_t obs_r;
+    obs_r.time.sec = 0;
+    obs_r.time.time = 0;
+    snapshot_r->getObservations()->addObservation(obs_r);
+    obsd_t obs_k;
+    obs_k.time.sec = 0;
+    obs_k.time.time = 1;
+    snapshot_k->getObservations()->addObservation(obs_k);
+
     // Random receiver position
     for (auto i = 0; i<100; i++)
     {
+        // clear satellites and ranges
+        snapshot_r->getSatellites().clear();
+        snapshot_k->getSatellites().clear();
+        snapshot_r->getRanges().clear();
+        snapshot_k->getRanges().clear();
+
+        // random setup
         x_r_LLA = computeRandomReceiverLatLonAlt();
         x_r_ECEF = latLonAltToEcef(x_r_LLA);
         d_ECEF = Vector3d::Random() * 10;
         x_k_ECEF = x_r_ECEF + d_ECEF;
         x_k_LLA = ecefToLatLonAlt(x_k_ECEF);
-        // TODO: random clock biases
-        double clock_r, clock_k;
+
+        double clock_r = Vector2d::Random()(0) * 1e-6;
+        double clock_k = Vector2d::Random()(0) * 1e-6;
 
         // groundtruth
         d_gt.head<3>() = d_ECEF;
-        d_gt(3) = clock_k - clock_r;
+        d_gt(3) = (clock_k - clock_r) * CLIGHT;
+
+        std::cout << "Iteration " << i << ":\n";
+        std::cout << std::setprecision(10) << "\tx_r_ECEF " << x_r_ECEF.transpose() << ":\n";
+        std::cout << "\tclock_r " << clock_r << ":\n";
+        std::cout << std::setprecision(10) << "\tx_k_ECEF " << x_k_ECEF.transpose() << ":\n";
+        std::cout << "\tclock_k " << clock_k << ":\n";
+        std::cout << "\td_gt " << d_gt.transpose() << ":\n";
 
         std::set<int> common_sats;
         std::set<int> raim_discarded_sats;
 
         // random visible satellites
-        for (auto j = 0; j<10; j++)
+        for (auto j = 0; j<N_sats; j++)
         {
             common_sats.insert(j);
 
             // Satellite r (random)
             computeRandomVisibleSatellite(x_r_LLA, sat_ENU, sat_ECEF, azel, range);
-            EXPECT_MATRIX_APPROX(azel, computeAzel(sat_ECEF, x_r_ECEF), 1e-6);
+            ASSERT_MATRIX_APPROX(azel, computeAzel(sat_ECEF, x_r_ECEF), 1e-3);
 
             Satellite sat_r({0,j,sat_ECEF, Vector3d::Zero(), 1.0, 0, 0, 1});
             snapshot_r->getSatellites().emplace(j, sat_r);
 
-            // TODO: compute range and add random clock bias
+            // Range r
+            Range range_r;
+            range_r.sat = j;
+            range_r.L_corrected = range + CLIGHT * clock_r;
+            range_r.L_var = 1;
+            range_r.L2_corrected = range_r.L_corrected;
+            range_r.L2_var = range_r.L_var;
+
+            snapshot_r->getRanges().emplace(j, range_r);
+
+            std::cout << "\tsat: " << j << "\n";
+            std::cout << "\t\tsat_r_ECEF " << sat_ECEF.transpose() << ":\n";
+            std::cout << "\t\trange_r.L_corrected " << range_r.L_corrected << ":\n";
 
             // Satellite k (random)
             computeRandomVisibleSatellite(x_k_LLA, sat_ENU, sat_ECEF, azel, range);
-            EXPECT_MATRIX_APPROX(azel, computeAzel(sat_ECEF, x_k_ECEF), 1e-6);
+            ASSERT_MATRIX_APPROX(azel, computeAzel(sat_ECEF, x_k_ECEF), 1e-3);
 
             Satellite sat_k({0,j,sat_ECEF, Vector3d::Zero(), 1.0, 0, 0, 1});
             snapshot_k->getSatellites().emplace(j, sat_k);
 
-            // TODO: compute range and add random clock bias
+            // Range k
+            Range range_k;
+            range_k.sat = j;
+            range_k.L_corrected = range + CLIGHT * clock_k;
+            range_k.L_var = 1;
+            range_k.L2_corrected = range_k.L_corrected;
+            range_k.L2_var = range_k.L_var;
+
+            snapshot_k->getRanges().emplace(j, range_k);
+
+            std::cout << "\t\tsat_k_ECEF " << sat_ECEF.transpose() << ":\n";
+            std::cout << "\t\trange_k.L_corrected " << range_k.L_corrected << ":\n";
         }
 
-        // TODO: randomly distort 1 satellite -> to be detected by RAIM
+        // Distort one range -> to be detected by RAIM
+        int wrong_sat1 = i % N_sats;
+        snapshot_k->getRanges().at(wrong_sat1).L_corrected += 20;
+        int wrong_sat2 = (i + N_sats / 2) % N_sats;
+        snapshot_r->getRanges().at(wrong_sat2).L_corrected -= 10;
 
+        // TDCP
+        d = Vector4d::Zero(); // initialize
         bool tdcp_ok = Tdcp(snapshot_r,
                             snapshot_k,
                             x_r_ECEF,
@@ -120,9 +184,14 @@ TEST(Tdcp, Tdcp)
                             raim_discarded_sats,
                             tdcp_params);
 
-        EXPECT_TRUE(tdcp_ok);
-        EXPECT_MATRIX_APPROX(d, d_gt, 1e-9);
-        EXPECT_LE(residual, 1e-9);
+        // CHECKS
+        std::cout << "CHECKS iteration " << i << std::endl;
+        ASSERT_EQ(raim_discarded_sats.size(), 2);
+        ASSERT_TRUE(raim_discarded_sats.count(wrong_sat1));
+        ASSERT_TRUE(raim_discarded_sats.count(wrong_sat2));
+        ASSERT_TRUE(tdcp_ok);
+        ASSERT_LE(residual, 1e-9);
+        ASSERT_MATRIX_APPROX(d, d_gt, 1e-6);
     }
 }
 
-- 
GitLab